Template:Image frame


before (Module:Chart) after (this module)
25,000
50,000
75,000
100,000
125,000
150,000
Before
During
After
Post mortem
Blah
Bloh
  •   Apple
  •   Banana
  •   Orange

Page Template:TemplateStyles sandbox/Ita140188/styles.css has no content.

 
150,000
 
125,000
 
100,000
 
75,000
 
50,000
 
25,000
Before
During
After
Post mortem
Blah
Bloh
  •   Apple
  •   Banana
  •   Orange


before (Module:Chart) after (this module)

Template:Image frame

Template:Image frame

IntegersEdit

Old chart module:
2.5
5
7.5
10
12.5
15
  •   leg1
  •   leg2
  •   leg3
  •   leg4
  •   leg5
  •   leg6
new module:

Page Template:TemplateStyles sandbox/Ita140188/styles.css has no content.

 
15
 
10
 
5
  •   leg1
  •   leg2
  •   leg3
  •   leg4
  •   leg5
  •   leg6

RocketsEdit

Template:Columns-start Template:Column

Rocket configurationsEdit

Page Template:TemplateStyles sandbox/Ita140188/styles.css has no content.

 
20
 
15
 
10
 
5

Template:Column

Launch sitesEdit

Page Template:TemplateStyles sandbox/Ita140188/styles.css has no content.

 
20
 
15
 
10
 
5
2010
'11
'12
'13
'14
'15
'16
'17
'18

Template:Columns-endTemplate:Columns-start Template:Column

Launch outcomesEdit

Page Template:TemplateStyles sandbox/Ita140188/styles.css has no content.

 
20
 
15
 
10
 
5
2010
'11
'12
'13
'14
'15
'16
'17
'18
  •   Loss before launch
  •   Loss during flight
  •   Partial failure
  •   Success

Template:Column

Booster landingsEdit

Page Template:TemplateStyles sandbox/Ita140188/styles.css has no content.

 
20
 
15
 
10
 
5
2010
'11
'12
'13
'14
'15
'16
'17
'18
  •   Ground pad failure
  •   Drone ship failure
  •   Ocean failure
  •   Parachutes failure
  •   Ground pad success
  •   Drone ship success
  •   Ocean touchdown
  •   No attempt

Template:Columns-end




Page Template:TemplateStyles sandbox/Ita140188/styles.css has no content.

 
60
 
50
 
40
 
30
 
20
 
10
Before
During
After
Post mortem

Page Template:TemplateStyles sandbox/Ita140188/styles.css has no content.

 
100
 
90
 
80
 
70
 
60
 
50
 
40
 
30
 
20
 
10
Before
During
After
very very long description just as an example
  •   Apple
  •   Banana


Page Template:TemplateStyles sandbox/Ita140188/styles.css has no content.

  •   Apple
  •   Banana
  •   Orange

Page Template:TemplateStyles sandbox/Ita140188/styles.css has no content.

 
150
 
125
 
100
 
75
 
50
 
25
Before
During
After
Post mortem
  •   Apple
  •   Banana
  •   Orange


Page Template:TemplateStyles sandbox/Ita140188/styles.css has no content.

 
150
 
125
 
100
 
75
 
50
 
25
1920
1930
1940
1950
1960
1970
1990
2000
2010
  •   Alabama
  •   Alaska
  •   Arizona
  •   Arkansas
  •   California
  •   Colorado
  •   Connecticut
  •   Delaware
  •   Florida
  •   Georgia
  •   Hawaii
  •   Idaho
  •   Illinois
  •   Indiana
  •   Iowa
  •   Kansas
  •   Kentucky
  •   Louisiana
  •   Maine
  •   Maryland
  •   Massachusetts

Test case for numerous narrow columnsEdit

Charting the history of rocket launches at Timeline of spaceflight.

Legacy Chart module
50
100
150
200
1957
1960
1965
1970
1975
1980
1985
1990
1995
2000
2005
2010
2015
2020
  •   Failure
  •   Partial failure
  •   Success
  •   Planned
Updated module

Page Template:TemplateStyles sandbox/Ita140188/styles.css has no content.

 
200
 
150
 
100
 
50
1957
1960
1965
1970
1975
1980
1985
1990
1995
2000
2005
2010
2015
2020
  •   Failure
  •   Partial failure
  •   Success
  •   Planned

Test case for negative values (still not working!!)Edit

Charting the GDP growth of Russia for the Economy of Russia article.

Legacy Chart module
1
2
3
4
5
6
7
8
9
10
'99
2000
2002
2004
2006
2008
2010
2012
2014
2016
'17
  •   Growth
  •   Recession
Updated module

Page Template:TemplateStyles sandbox/Ita140188/styles.css has no content.

 
10
 
9
 
8
 
7
 
6
 
5
 
4
 
3
 
2
 
1
'99
2000
2002
2004
2006
2008
2010
2012
2014
2016
'17
  •   Growth
  •   Recession

Page Template:TemplateStyles sandbox/Ita140188/styles.css has no content.

 
10
 
9
 
8
 
7
 
6
 
5
 
4
 
3
 
2
 
1
'99
2000
2002
2004
2006
2008
2010
2012
2014
2016
'17

Drawing Pie charts: "pie chart"Edit

ParametersEdit

parameter name what it does
delimiter string to delimit multiple values when given. default to colon ( : ). normally you do not want to touch this, it's provided for the off-chance you'll want to use colon as part of one of the parameters.
radius number. The radius of the pie in pixels
slices Tuples, in parenthesis. Use delimiter inside the tuple:
( Value1 : Name1 : Color1 : Link1  ) ( Value2 : Name2 : Color2 : Link2 ) ...

The values are numbers. The numbers can be integers or decimal fractions, or using the scientific notation: 7.24e6, 7,240,000, or 7240000.00 are all acceptable for 7 Million and 240 thousands.

Names are strings. Colors are optional. you can use any Web colors, such as "red" or "#FF0000". Up to 26 default colors are defined, but if your pie has more than 26 slices, you must define the colors of slice #27 and up. Links can be external or internal links, including linking to internal anchors and paragraphs in the same article, like so: [[Article|Tooltip]] for internal link, [[#Paragraph name|Tooltip]] for linking to an anchor in same article, or [http://example.org Tooltip] for external link.

slice n alternative syntax to "slices". n is the slice number, beginning with 1. make sure not to skip: if you define "slice 1", "slice 2", "slice 4", "slice 5"..., skipping slice 3, only the first two slices will be shown. this syntax is incompatible with "slices", i.e., they should not be used in conjunction in the same invocation. Using both "slices" and "slice n" in the same invocation will cause unpredictable results. The value is like a single "tuple" as explained above, but without the parenthesis:
 | slice 1 = Value1 : Name1 : Color1 : Link1
 | slice 2 = Value2 : Name2 : Color2 : Link2
 | ...

This syntax allows you to use parenthesis in names, links, and colors.

percent if used, the percentage of each slice will be calculated and added to the legend: so if you have two slices, like so: ( 1 : Younglings ) ( 3 : elders ), and use define "percent", the legends will become "Younglings: 1 (25%)" and "Elders: 3 (75%)", instead of simply "Younglings: 1" and "Elders: 3". Any non-empty value means "yes". To say "no", simply do not supply this parameter at all, or leave the value blank.
units prefix used in the legend. e.g., defining "units prefix=$", values will show as "$500" instead of "500" in the legends
units suffix ditto for units suffix. use, e.g. "Kg" so values will show as 88Kg instead of 88 in legend. underscore ("_") are replaced by spaces, to allow a space between the value and the suffix.
hide group legends Setting to true prevents displaying of the group legends under the chart. Any non-empty value means "yes". To say "no", simply do not supply this parameter at all, or leave the value blank.

ExamplesEdit

<imagemap> File:Circle frame.svg|300px poly 100 100 200 100 199 99 199 97 199 95 199 93 199 91 199 89 199 87 198 85 198 83 198 81 197 79 197 77 196 75 196 73 195 71 194 69 194 67 193 65 192 63 192 62 191 60 190 58 189 56 188 54 187 53 186 51 185 49 184 47 183 46 182 44 181 42 180 41 178 39 177 38 176 36 175 35 173 33 172 32 171 30 169 29 168 27 166 26 165 25 163 23 162 22 160 21 158 20 157 19 155 17 154 16 152 15 150 14 148 13 147 12 100 100 Apples: 1,000,000 Tonne (17.2%) poly 100 100 147 12 145 11 143 11 141 10 140 9 138 8 136 7 134 7 132 6 130 5 128 5 126 4 125 4 123 3 121 3 119 2 117 2 115 2 113 1 111 1 109 1 107 1 105 1 103 1 101 1 99 1 97 1 95 1 93 1 91 1 89 1 87 1 85 2 83 2 81 2 79 3 77 3 75 4 73 4 71 5 69 5 67 6 65 6 64 7 62 8 60 9 58 9 56 10 54 11 53 12 51 13 49 14 47 15 46 16 44 17 42 18 41 20 39 21 38 22 36 23 35 24 33 26 32 27 30 28 29 30 27 31 26 33 25 34 23 36 22 37 21 39 20 40 18 42 17 44 16 45 15 47 14 49 13 50 12 52 11 54 10 56 9 58 8 59 8 61 7 63 6 65 5 67 5 69 4 71 4 72 3 74 2 76 2 78 2 80 1 82 1 84 1 86 0 88 0 90 0 92 0 94 0 96 0 98 0 100 0 102 0 104 0 106 0 108 0 110 100 100 Bananas: 2,000,000 Tonne (34.3%) poly 100 100 0 110 0 112 0 114 1 116 1 118 1 120 2 122 2 123 3 125 3 127 4 129 4 131 5 133 6 135 6 137 7 139 8 141 9 142 10 144 10 146 11 148 12 149 13 151 14 153 15 155 16 156 18 158 19 160 20 161 21 163 22 164 24 166 25 167 26 169 28 170 29 172 31 173 32 174 34 176 35 177 37 178 38 180 40 181 41 182 43 183 45 184 46 185 48 186 50 187 52 188 53 189 55 190 57 191 59 192 61 193 62 193 64 194 66 195 68 195 70 196 72 197 74 197 76 198 78 198 80 199 82 199 84 199 86 200 88 200 90 200 92 200 94 200 96 200 98 200 100 200 102 200 104 200 106 200 107 200 100 100 Apricots: 1,440,000 Tonne (24.7%) poly 100 100 107 200 109 200 111 200 113 200 115 199 117 199 119 199 121 198 123 198 125 197 126 197 128 196 130 196 132 195 134 194 136 194 138 193 140 192 141 191 143 190 145 190 147 189 149 188 150 187 152 186 154 185 155 183 157 182 159 181 160 180 162 179 163 177 165 176 166 175 168 173 169 173 100 100 Pears poly 100 100 169 173 170 171 171 170 173 169 174 167 175 166 177 164 178 162 179 161 180 159 182 158 183 156 184 154 185 153 186 151 187 149 188 147 189 146 190 144 190 142 191 140 192 138 193 137 193 135 194 133 195 131 195 129 196 127 196 125 197 123 197 121 198 119 198 117 198 115 199 113 199 111 199 109 199 107 199 105 199 103 199 101 200 101 100 100 Pineapples: 750,000 Tonne (12.9%) desc none </imagemap>

  •   Apples: 1,000,000 Tonne (17.2%)
  •   Bananas: 2,000,000 Tonne (34.3%)
  •   Apricots: 1,440,000 Tonne (24.7%)
  •   Pears: 640,000 Tonne (11.0%)
  •   Pineapples: 750,000 Tonne (12.9%)


<imagemap> Image:Circle frame.svg|300px poly 100 100 200 100 199 99 199 97 199 95 199 93 199 91 199 89 199 87 198 85 198 83 198 81 197 79 197 77 196 75 196 73 195 71 194 69 194 67 193 65 192 63 192 62 191 60 190 58 189 56 188 54 187 53 186 51 185 49 184 47 183 46 182 44 181 42 180 41 178 39 177 38 176 36 175 35 173 33 172 32 171 30 169 29 168 27 166 26 165 25 163 23 162 22 160 21 158 20 157 19 155 17 154 16 152 15 150 14 148 13 147 12 100 100 Apples: 1,000,000 Tonne (17.2%) poly 100 100 147 12 145 11 143 11 141 10 140 9 138 8 136 7 134 7 132 6 130 5 128 5 126 4 125 4 123 3 121 3 119 2 117 2 115 2 113 1 111 1 109 1 107 1 105 1 103 1 101 1 99 1 97 1 95 1 93 1 91 1 89 1 87 1 85 2 83 2 81 2 79 3 77 3 75 4 73 4 71 5 69 5 67 6 65 6 64 7 62 8 60 9 58 9 56 10 54 11 53 12 51 13 49 14 47 15 46 16 44 17 42 18 41 20 39 21 38 22 36 23 35 24 33 26 32 27 30 28 29 30 27 31 26 33 25 34 23 36 22 37 21 39 20 40 18 42 17 44 16 45 15 47 14 49 13 50 12 52 11 54 10 56 9 58 8 59 8 61 7 63 6 65 5 67 5 69 4 71 4 72 3 74 2 76 2 78 2 80 1 82 1 84 1 86 0 88 0 90 0 92 0 94 0 96 0 98 0 100 0 102 0 104 0 106 0 108 0 110 100 100 Bananas: 2,000,000 Tonne (34.3%) poly 100 100 0 110 0 112 0 114 1 116 1 118 1 120 2 122 2 123 3 125 3 127 4 129 4 131 5 133 6 135 6 137 7 139 8 141 9 142 10 144 10 146 11 148 12 149 13 151 14 153 15 155 16 156 18 158 19 160 20 161 21 163 22 164 24 166 25 167 26 169 28 170 29 172 31 173 32 174 34 176 35 177 37 178 38 180 40 181 41 182 43 183 45 184 46 185 48 186 50 187 52 188 53 189 55 190 57 191 59 192 61 193 62 193 64 194 66 195 68 195 70 196 72 197 74 197 76 198 78 198 80 199 82 199 84 199 86 200 88 200 90 200 92 200 94 200 96 200 98 200 100 200 102 200 104 200 106 200 107 200 100 100 Apricots: 1,440,000 Tonne (24.7%) poly 100 100 107 200 109 200 111 200 113 200 115 199 117 199 119 199 121 198 123 198 125 197 126 197 128 196 130 196 132 195 134 194 136 194 138 193 140 192 141 191 143 190 145 190 147 189 149 188 150 187 152 186 154 185 155 183 157 182 159 181 160 180 162 179 163 177 165 176 166 175 168 173 169 173 100 100 Pears poly 100 100 169 173 170 171 171 170 173 169 174 167 175 166 177 164 178 162 179 161 180 159 182 158 183 156 184 154 185 153 186 151 187 149 188 147 189 146 190 144 190 142 191 140 192 138 193 137 193 135 194 133 195 131 195 129 196 127 196 125 197 123 197 121 198 119 198 117 198 115 199 113 199 111 199 109 199 107 199 105 199 103 199 101 200 101 100 100 Pineapples: 750,000 Tonne (12.9%) desc none </imagemap>

  •   Apples: 1,000,000 Tonne (17.2%)
  •   Bananas: 2,000,000 Tonne (34.3%)
  •   Apricots: 1,440,000 Tonne (24.7%)
  •   Pears: 640,000 Tonne (11.0%)
  •   Pineapples: 750,000 Tonne (12.9%)



<imagemap> File:Circle frame.svg|400px poly 100 100 200 100 199 99 100 100 1: 1 Units (0.2%) poly 100 100 199 99 199 97 199 95 199 93 199 91 199 90 100 100 7: 7 Units (1.5%) poly 100 100 199 90 199 88 198 86 198 84 198 82 197 80 197 80 100 100 8: 8 Units (1.7%) poly 100 100 197 80 197 78 196 76 196 74 195 72 195 70 194 68 100 100 9: 9 Units (1.9%) poly 100 100 194 68 193 66 193 64 192 62 191 61 190 59 190 57 189 56 100 100 10: 10 Units (2.1%) poly 100 100 189 56 188 54 187 52 186 51 185 49 184 47 183 46 182 44 182 43 100 100 11: 11 Units (2.3%) poly 100 100 182 43 180 42 179 40 178 39 177 37 176 36 174 34 173 33 172 31 100 100 12: 12 Units (2.5%) poly 100 100 172 31 170 30 169 28 167 27 166 26 164 24 163 23 161 22 160 21 159 20 100 100 13: 13 Units (2.7%) poly 100 100 159 20 157 19 155 18 154 17 152 15 150 14 149 13 147 12 145 12 143 11 143 10 100 100 14: 14 Units (2.9%) poly 100 100 143 10 141 10 139 9 137 8 136 7 134 7 132 6 130 5 128 5 126 4 124 4 100 100 15: 15 Units (3.2%) poly 100 100 124 4 122 3 120 3 118 2 116 2 115 2 113 1 111 1 109 1 107 1 105 1 103 1 100 100 16: 16 Units (3.4%) poly 100 100 103 1 101 1 99 1 97 1 95 1 93 1 91 1 89 1 87 1 86 1 84 2 82 2 81 2 100 100 17: 17 Units (3.6%) poly 100 100 81 2 79 3 77 3 75 3 73 4 71 5 69 5 68 6 66 6 64 7 62 8 60 9 59 9 100 100 18: 18 Units (3.8%) poly 100 100 59 9 57 10 55 11 53 12 51 13 50 14 48 15 46 16 44 17 43 18 41 19 40 20 38 22 37 22 100 100 19: 19 Units (4.0%) poly 100 100 37 22 36 24 34 25 33 26 31 28 30 29 28 30 27 32 25 33 24 35 23 36 22 38 20 39 19 41 19 41 100 100 20: 20 Units (4.2%) poly 100 100 19 41 18 43 17 45 16 46 14 48 13 50 12 51 11 53 11 55 10 57 9 58 8 60 7 62 6 64 6 66 100 100 21: 21 Units (4.4%) poly 100 100 6 66 5 67 4 69 4 71 3 73 3 75 2 77 2 79 1 81 1 83 1 85 0 87 0 89 0 91 0 93 0 94 100 100 22: 22 Units (4.6%) poly 100 100 0 94 0 96 0 98 0 100 0 102 0 104 0 106 0 108 0 110 0 112 0 114 1 116 1 118 1 120 2 122 2 124 2 124 100 100 23: 23 Units (4.8%) poly 100 100 2 124 3 126 3 128 4 130 5 132 5 134 6 136 7 137 7 139 8 141 9 143 10 145 11 146 12 148 13 150 14 152 14 153 100 100 24: 24 Units (5.0%) poly 100 100 14 153 16 155 17 157 18 158 19 160 20 161 21 163 23 164 24 166 25 168 27 169 28 170 29 172 31 173 32 175 34 176 35 177 36 178 100 100 25: 25 Units (5.3%) poly 100 100 36 178 38 179 39 180 41 182 43 183 44 184 46 185 48 186 49 187 51 188 53 189 55 190 56 191 58 192 60 192 62 193 64 194 66 195 66 195 100 100 26: 26 Units (5.5%) poly 100 100 66 195 68 195 70 196 72 197 73 197 75 198 77 198 79 198 81 199 83 199 85 199 87 200 89 200 91 200 93 200 95 200 97 200 99 200 101 200 100 100 27: 27 Units (5.7%) poly 100 100 101 200 103 200 105 200 107 200 109 200 111 200 113 200 115 199 117 199 119 199 121 198 123 198 125 197 126 197 128 196 130 196 132 195 134 194 136 194 137 193 100 100 28: 28 Units (5.9%) poly 100 100 137 193 139 192 141 192 142 191 144 190 146 189 148 188 149 187 151 186 153 185 155 184 156 183 158 182 159 181 161 179 163 178 164 177 166 175 167 174 169 173 169 173 100 100 29: 29 Units (6.1%) poly 100 100 169 173 170 171 172 170 173 168 174 167 176 165 177 164 178 162 179 161 181 159 182 157 183 156 184 154 185 152 186 151 187 149 188 147 189 145 190 144 191 142 191 140 100 100 30: 30 Units (6.3%) poly 100 100 191 140 192 138 193 137 193 135 194 133 195 131 195 129 196 127 196 125 197 123 197 121 198 119 198 117 198 115 199 113 199 111 199 109 199 107 199 105 199 103 199 101 200 101 100 100 31: 31 Units (6.5%) desc none </imagemap>

  •   1: 1 Units (0.2%)
  •   7: 7 Units (1.5%)
  •   8: 8 Units (1.7%)
  •   9: 9 Units (1.9%)
  •   10: 10 Units (2.1%)
  •   11: 11 Units (2.3%)
  •   12: 12 Units (2.5%)
  •   13: 13 Units (2.7%)
  •   14: 14 Units (2.9%)
  •   15: 15 Units (3.2%)
  •   16: 16 Units (3.4%)
  •   17: 17 Units (3.6%)
  •   18: 18 Units (3.8%)
  •   19: 19 Units (4.0%)
  •   20: 20 Units (4.2%)
  •   21: 21 Units (4.4%)
  •   22: 22 Units (4.6%)
  •   23: 23 Units (4.8%)
  •   24: 24 Units (5.0%)
  •   25: 25 Units (5.3%)
  •   26: 26 Units (5.5%)
  •   27: 27 Units (5.7%)
  •   28: 28 Units (5.9%)
  •   29: 29 Units (6.1%)
  •   30: 30 Units (6.3%)
  •   31: 31 Units (6.5%)

<imagemap> Image:Circle frame.svg|400px poly 100 100 200 100 199 99 100 100 1: 1 Units (0.2%) poly 100 100 199 99 199 97 199 95 199 93 199 91 199 90 100 100 7: 7 Units (1.5%) poly 100 100 199 90 199 88 198 86 198 84 198 82 197 80 197 80 100 100 8: 8 Units (1.7%) poly 100 100 197 80 197 78 196 76 196 74 195 72 195 70 194 68 100 100 9: 9 Units (1.9%) poly 100 100 194 68 193 66 193 64 192 62 191 61 190 59 190 57 189 56 100 100 10: 10 Units (2.1%) poly 100 100 189 56 188 54 187 52 186 51 185 49 184 47 183 46 182 44 182 43 100 100 11: 11 Units (2.3%) poly 100 100 182 43 180 42 179 40 178 39 177 37 176 36 174 34 173 33 172 31 100 100 12: 12 Units (2.5%) poly 100 100 172 31 170 30 169 28 167 27 166 26 164 24 163 23 161 22 160 21 159 20 100 100 13: 13 Units (2.7%) poly 100 100 159 20 157 19 155 18 154 17 152 15 150 14 149 13 147 12 145 12 143 11 143 10 100 100 14: 14 Units (2.9%) poly 100 100 143 10 141 10 139 9 137 8 136 7 134 7 132 6 130 5 128 5 126 4 124 4 100 100 15: 15 Units (3.2%) poly 100 100 124 4 122 3 120 3 118 2 116 2 115 2 113 1 111 1 109 1 107 1 105 1 103 1 100 100 16: 16 Units (3.4%) poly 100 100 103 1 101 1 99 1 97 1 95 1 93 1 91 1 89 1 87 1 86 1 84 2 82 2 81 2 100 100 17: 17 Units (3.6%) poly 100 100 81 2 79 3 77 3 75 3 73 4 71 5 69 5 68 6 66 6 64 7 62 8 60 9 59 9 100 100 18: 18 Units (3.8%) poly 100 100 59 9 57 10 55 11 53 12 51 13 50 14 48 15 46 16 44 17 43 18 41 19 40 20 38 22 37 22 100 100 19: 19 Units (4.0%) poly 100 100 37 22 36 24 34 25 33 26 31 28 30 29 28 30 27 32 25 33 24 35 23 36 22 38 20 39 19 41 19 41 100 100 20: 20 Units (4.2%) poly 100 100 19 41 18 43 17 45 16 46 14 48 13 50 12 51 11 53 11 55 10 57 9 58 8 60 7 62 6 64 6 66 100 100 21: 21 Units (4.4%) poly 100 100 6 66 5 67 4 69 4 71 3 73 3 75 2 77 2 79 1 81 1 83 1 85 0 87 0 89 0 91 0 93 0 94 100 100 22: 22 Units (4.6%) poly 100 100 0 94 0 96 0 98 0 100 0 102 0 104 0 106 0 108 0 110 0 112 0 114 1 116 1 118 1 120 2 122 2 124 2 124 100 100 23: 23 Units (4.8%) poly 100 100 2 124 3 126 3 128 4 130 5 132 5 134 6 136 7 137 7 139 8 141 9 143 10 145 11 146 12 148 13 150 14 152 14 153 100 100 24: 24 Units (5.0%) poly 100 100 14 153 16 155 17 157 18 158 19 160 20 161 21 163 23 164 24 166 25 168 27 169 28 170 29 172 31 173 32 175 34 176 35 177 36 178 100 100 25: 25 Units (5.3%) poly 100 100 36 178 38 179 39 180 41 182 43 183 44 184 46 185 48 186 49 187 51 188 53 189 55 190 56 191 58 192 60 192 62 193 64 194 66 195 66 195 100 100 26: 26 Units (5.5%) poly 100 100 66 195 68 195 70 196 72 197 73 197 75 198 77 198 79 198 81 199 83 199 85 199 87 200 89 200 91 200 93 200 95 200 97 200 99 200 101 200 100 100 27: 27 Units (5.7%) poly 100 100 101 200 103 200 105 200 107 200 109 200 111 200 113 200 115 199 117 199 119 199 121 198 123 198 125 197 126 197 128 196 130 196 132 195 134 194 136 194 137 193 100 100 28: 28 Units (5.9%) poly 100 100 137 193 139 192 141 192 142 191 144 190 146 189 148 188 149 187 151 186 153 185 155 184 156 183 158 182 159 181 161 179 163 178 164 177 166 175 167 174 169 173 169 173 100 100 29: 29 Units (6.1%) poly 100 100 169 173 170 171 172 170 173 168 174 167 176 165 177 164 178 162 179 161 181 159 182 157 183 156 184 154 185 152 186 151 187 149 188 147 189 145 190 144 191 142 191 140 100 100 30: 30 Units (6.3%) poly 100 100 191 140 192 138 193 137 193 135 194 133 195 131 195 129 196 127 196 125 197 123 197 121 198 119 198 117 198 115 199 113 199 111 199 109 199 107 199 105 199 103 199 101 200 101 100 100 31: 31 Units (6.5%) desc none </imagemap>

  •   1: 1 Units (0.2%)
  •   7: 7 Units (1.5%)
  •   8: 8 Units (1.7%)
  •   9: 9 Units (1.9%)
  •   10: 10 Units (2.1%)
  •   11: 11 Units (2.3%)
  •   12: 12 Units (2.5%)
  •   13: 13 Units (2.7%)
  •   14: 14 Units (2.9%)
  •   15: 15 Units (3.2%)
  •   16: 16 Units (3.4%)
  •   17: 17 Units (3.6%)
  •   18: 18 Units (3.8%)
  •   19: 19 Units (4.0%)
  •   20: 20 Units (4.2%)
  •   21: 21 Units (4.4%)
  •   22: 22 Units (4.6%)
  •   23: 23 Units (4.8%)
  •   24: 24 Units (5.0%)
  •   25: 25 Units (5.3%)
  •   26: 26 Units (5.5%)
  •   27: 27 Units (5.7%)
  •   28: 28 Units (5.9%)
  •   29: 29 Units (6.1%)
  •   30: 30 Units (6.3%)
  •   31: 31 Units (6.5%)

--<source lang=lua>
--[[
    keywords are used for languages: they are the names of the actual
    parameters of the template
]]

local keywords = {
    barChart = 'bar chart',
    pieChart = 'pie chart',
    width = 'width',
    height = 'height',
    stack = 'stack',
    colors = 'colors',
    group = 'group',
    xlegend = 'x legends',
    tooltip = 'tooltip',
    accumulateTooltip = 'tooltip value accumulation',
    links = 'links',
    defcolor = 'default color',
    scalePerGroup = 'scale per group',
    unitsPrefix = 'units prefix',
    unitsSuffix = 'units suffix',
    groupNames = 'group names',
    hideGroupLegends = 'hide group legends',
    optint = 'only integer values',
    slices = 'slices',
    slice = 'slice',
    radius = 'radius',
    percent = 'percent',

} -- here is what you want to translate



local defColors = mw.loadData("Module:Chart/Default colors")
local hideGroupLegends
local optint

local function nulOrWhitespace( s )
    return not s or mw.text.trim( s ) == ''
end

local function createGroupList( tab, legends, cols )
    if #legends > 1 and not hideGroupLegends then
        table.insert( tab, mw.text.tag( 'div' ) )
        local list = {}
        local spanStyle = "padding:0 1em;background-color:%s;border:1px solid %s;margin-right:1em;-webkit-print-color-adjust:exact;"
        for gi = 1, #legends do
            local span = mw.text.tag( 'span', { style = string.format( spanStyle, cols[gi], cols[gi] ) }, '&nbsp;' ) .. ' '..  legends[gi]
            table.insert( list, mw.text.tag( 'li', {}, span ) )
        end
        table.insert( tab,
            mw.text.tag( 'ul',
                {style="width:100%;list-style:none;-webkit-column-width:12em;-moz-column-width:12em;column-width:12em;"},
                table.concat( list, '\n' )
            )
        )
        table.insert( tab, '</div>' )
    end
end


function pieChart( frame )
    local res, imslices, args = {}, {}, frame.args
    local radius
    local values, colors, names, legends, links = {}, {}, {}, {}, {}
    local delimiter = args.delimiter or ':'
    local lang = mw.getContentLanguage()

    function getArg( s, def, subst, with )
        local result = args[keywords[s]] or def or ''
        if subst and with then result = mw.ustring.gsub( result, subst, with ) end
        return result
    end

    function analyzeParams()
        function addSlice( i, slice )
            local value, name, color, link = unpack( mw.text.split( slice, '%s*' .. delimiter .. '%s*' ) )
            values[i] = tonumber( lang:parseFormattedNumber( value ) )
                or error( string.format( 'Slice %d: "%s", first item("%s") could not be parsed as a number', i, value or '', sliceStr ) )
            colors[i] = not nulOrWhitespace( color ) and color or defColors[i * 2]
            names[i] = name or ''
            links[i] = link
        end
        
        radius = getArg( 'radius', 150 )
        hideGroupLegends = not nulOrWhitespace( args[keywords.hideGroupLegends] )
        local slicesStr = getArg( 'slices' )
        local prefix = getArg( 'unitsPrefix', '', '_', ' ' )
        local suffix = getArg( 'unitsSuffix', '', '_', ' ' )
        local percent = args[keywords.percent]
        local sum = 0
        local i, value = 0
        for slice in mw.ustring.gmatch( slicesStr or '', "%b()" ) do
            i = i + 1
            addSlice( i, mw.ustring.match( slice, '^%(%s*(.-)%s*%)$' ) )
        end
        
        for k, v in pairs(args) do
            local ind = mw.ustring.match( k, '^' .. keywords.slice .. '%s+(%d+)$' )
            if ind then addSlice( tonumber( ind ), v ) end
        end
        
        for _, val in ipairs( values ) do sum = sum + val end
        for i, value in ipairs( values ) do
            local addprec = percent and string.format( ' (%0.1f%%)', value / sum * 100 ) or ''
            legends[i] = mw.ustring.format( '%s: %s%s%s%s', names[i], prefix, lang:formatNum( value ), suffix, addprec )
            links[i] = mw.text.trim( links[i] or mw.ustring.format( '[[#noSuchAnchor|%s]]', legends[i] ) )
        end
    end

    function addRes( ... )
        for _, v in pairs( { ... } ) do
            table.insert( res, v )
        end
    end

    function createImageMap()
        addRes( '{{#tag:imagemap|', 'Image:Circle frame.svg{{!}}' .. ( radius * 2 ) .. 'px' )
        addRes( unpack( imslices ) )
        addRes( 'desc none', '}}' )
    end

    function drawSlice( i, q, start )
        local color = colors[i]
        local angle = start * 2 * math.pi
        local sin, cos = math.abs( math.sin( angle ) ), math.abs( math.cos( angle ) )
        local wsin, wcos = sin * radius, cos * radius
        local s1, s2, w1, w2, w3, w4, width, border
        local style
        if q == 1 then
            border = 'left'
            w1, w2, w3, w4 = 0, 0, wsin, wcos
            s1, s2 = 'bottom', 'left'
        elseif q == 2 then
            border = 'bottom'
            w1, w2, w3, w4 = 0, wcos, wsin, 0
            s1, s2 = 'bottom', 'right'
        elseif q == 3 then
            border = 'right'
            w1, w2, w3, w4 = wsin, wcos, 0, 0
            s1, s2 = 'top', 'right'
        else
            border = 'top'
            w1, w2, w3, w4 = wsin, 0, 0, wcos
            s1, s2 = 'top', 'left'
        end

        local style = string.format( 'border:solid transparent;position:absolute;%s:%spx;%s:%spx;width:%spx;height:%spx', s1, radius, s2, radius, radius, radius )
        if start <= ( q - 1 ) * 0.25 then
            style = string.format( '%s;border:0;background-color:%s', style, color )
        else
            style = string.format( '%s;border-width:%spx %spx %spx %spx;border-%s-color:%s', style, w1, w2, w3, w4, border, color )
        end
        addRes( mw.text.tag( 'div', { style = style }, '' ) )
    end

    function createSlices()
        function coordsOfAngle( angle )
            return ( 100 + math.floor( 100 * math.cos( angle ) ) ) .. ' ' .. ( 100 - math.floor( 100 * math.sin( angle ) ) )
        end

        local sum, start = 0, 0
        for _, value in ipairs( values ) do sum = sum + value end
        for i, value in ipairs(values) do
            local poly = { 'poly 100 100' }
            local startC, endC =  start / sum, ( start + value ) / sum
            local startQ, endQ = math.floor( startC * 4 + 1 ), math.floor( endC * 4 + 1 )
            for q = startQ, math.min( endQ, 4 ) do drawSlice( i, q, startC ) end
            for angle = startC * 2 * math.pi, endC * 2 * math.pi, 0.02 do
                table.insert( poly,  coordsOfAngle( angle ) )
            end
            table.insert( poly, coordsOfAngle( endC * 2 * math.pi ) .. ' 100 100 ' .. links[i] )
            table.insert( imslices, table.concat( poly, ' ' ) )
            start = start + values[i]
        end
    end

    analyzeParams()
    if #values == 0 then error( "no slices found - can't draw pie chart" ) end
    addRes( mw.text.tag( 'div', { class = 'chart noresize', style = string.format( 'margin-top:0.5em;max-width:%spx;', radius * 2 ) } ) )
    addRes( mw.text.tag( 'div', { style = string.format( 'position:relative;min-width:%spx;min-height:%spx;max-width:%spx;overflow:hidden;', radius * 2, radius * 2, radius * 2 ) } ) )
    createSlices()
    addRes( mw.text.tag( 'div', { style = string.format( 'position:absolute;min-width:%spx;min-height:%spx;overflow:hidden;', radius * 2, radius * 2 ) } ) )
    createImageMap()
    addRes( '</div>' ) -- close "position:relative" div that contains slices and imagemap.
    addRes( '</div>' ) -- close "position:relative" div that contains slices and imagemap.
    createGroupList( res, legends, colors ) -- legends
    addRes( '</div>' ) -- close containing div
    return frame:preprocess( table.concat( res, '\n' ) )
end


function barChart( frame )
	
	local res = {}
    local args = frame.args -- can be changed to frame:getParent().args
    local values, xlegends, colors, tooltips, yscales, yscalesneg = {}, {}, {}, {} ,{}, {}, {}, {}
    local groupNames, unitsSuffix, unitsPrefix, links = {}, {}, {}, {}
    local width, height, stack, delimiter = 500, 350, false, args.delimiter or ':'
    local chartWidth, chartHeight, defcolor, scalePerGroup, accumulateTooltip

    local numGroups, numValues
    local scaleWidth
	
	table.insert( res, frame:extensionTag{ name = 'templatestyles', args = { src = 'TemplateStyles sandbox/Ita140188/styles.css'} })

	function createGroupList( tab, legends, cols )
	    if #legends > 1 and not hideGroupLegends then
	        table.insert( tab, mw.text.tag( 'div', { style = string.format( "width:%spx;", chartWidth ) } ) )
	        local list = {}
	        local spanStyle = "padding:0 1em;background-color:%s;border:1px solid %s;margin-right:1em;-webkit-print-color-adjust:exact;"
	        for gi = 1, #legends do
	            local span = mw.text.tag( 'span', { style = string.format( spanStyle, cols[gi], cols[gi] ) }, '&nbsp;' ) .. ' '..  legends[gi]
	            table.insert( list, mw.text.tag( 'li', {}, span ) )
	        end
	        table.insert( tab,
	            mw.text.tag( 'ul',
	                {style="width:100%;list-style:none;-webkit-column-width:12em;-moz-column-width:12em;column-width:12em;"},
	                table.concat( list, '\n' )
	            )
	        )
	        table.insert( tab, '</div>' )
	    end
	end



    function validate()
        function asGroups( name, tab, toDuplicate, emptyOK )
            if #tab == 0 and not emptyOK then
                error( "must supply values for " .. keywords[name] )
            end
            if #tab == 1 and toDuplicate then
                for i = 2, numGroups do tab[i] = tab[1] end
            end
            if #tab > 0 and #tab ~= numGroups then
                error ( keywords[name] .. ' must contain the same number of items as the number of groups, but it contains ' .. #tab .. ' items and there are ' .. numGroups .. ' groups')
            end
        end

        -- do all sorts of validation here, so we can assume all params are good from now on.
        -- among other things, replace numerical values with mw.language:parseFormattedNumber() result


        chartHeight = height - 80
        numGroups = #values
        numValues = #values[1]
        defcolor = defcolor or 'blue'
        colors[1] = colors[1] or defcolor
        scaleWidth = scalePerGroup and 80 * numGroups or 30
        chartWidth = width -scaleWidth
        asGroups( 'unitsPrefix', unitsPrefix, true, true )
        asGroups( 'unitsSuffix', unitsSuffix, true, true )
        asGroups( 'colors', colors, true, true )
        asGroups( 'groupNames', groupNames, false, false )
        if stack and scalePerGroup then
            error( string.format( 'Illegal settings: %s and %s are incompatible.', keyword.stack, keyword.scalePerGroup ) )
        end
        for gi = 2, numGroups do
            if #values[gi] ~= numValues then error( keywords.group .. " " .. gi .. " does not have same number of values as " .. keywords.group .. " 1" ) end
        end
        if #xlegends ~= numValues then error( 'Illegal number of ' .. keywords.xlegend .. '. Should be exactly ' .. numValues ) end
    end

    function extractParams()
        function testone( keyword, key, val, tab )
            i = keyword == key and 0 or key:match( keyword .. "%s+(%d+)" )
            if not i then return end
            i = tonumber( i ) or error("Expect numerical index for key " .. keyword .. " instead of '" .. key .. "'")
            if i > 0 then tab[i] = {} end
            for s in mw.text.gsplit( val, '%s*' .. delimiter .. '%s*' ) do
                table.insert( i == 0 and tab or tab[i], s )
            end
            return true
        end

        for k, v in pairs( args ) do
            if k == keywords.width then
                width = tonumber( v )
                if not width or width < 200 then
                    error( 'Illegal width value (must be a number, and at least 200): ' .. v )
                end
            elseif k == keywords.height then
                height = tonumber( v )
                if not height or height < 200 then
                    error( 'Illegal height value (must be a number, and at least 200): ' .. v )
                end
            elseif k == keywords.stack then stack = true
            elseif k == keywords.optint then optint = true
            elseif k == keywords.scalePerGroup then scalePerGroup = true
            elseif k == keywords.defcolor then defcolor = v
            elseif k == keywords.accumulateTooltip then accumulateTooltip = not nulOrWhitespace( v )
            elseif k == keywords.hideGroupLegends then hideGroupLegends = not nulOrWhitespace( v )
            else
                for keyword, tab in pairs( {
                    group = values,
                    xlegend = xlegends,
                    colors = colors,
                    tooltip = tooltips,
                    unitsPrefix = unitsPrefix,
                    unitsSuffix = unitsSuffix,
                    groupNames = groupNames,
                    links = links,
                    } ) do
                        if testone( keywords[keyword], k, v, tab )
                            then break
                        end
                end
            end
        end
    end

    function roundup( x ) -- returns the next round number: eg., for 30 to 39.999 will return 40, for 3000 to 3999.99 wil return 4000. for 10 - 14.999 will return 15.
        local ordermag = 10 ^ math.floor( math.log10( x ) )
        local normalized = x /  ordermag
        local top = normalized >= 1.5 and ( math.floor( normalized + 1 ) ) or 1.5
        return ordermag * top, top, ordermag
    end

    function calcHeightLimits() -- if limits were passed by user, use them, otherwise calculate. for "stack" there's only one limet.
        if stack then
            local sums = {}
            for _, group in pairs( values ) do
                for i, val in ipairs( group ) do sums[i] = ( sums[i] or 0 ) + val end
            end
            local sum = math.max( unpack( sums ) )
            local sumneg = math.min( unpack( sums ) )
            for i = 1, #values do 
            	yscales[i] = sum 
            	yscalesneg[i] = 0 -- -sumneg
            end
        else
            for i, group in ipairs( values ) do 
            	yscales[i] = math.max( unpack( group ) ) 
            	yscalesneg[i] = -math.min( unpack( group ) ) 
            end
        end
        for i, scale in ipairs( yscales ) do yscales[i] = roundup( scale * 0.9999 ) end
        for i, scale in ipairs( yscalesneg ) do yscalesneg[i] = roundup( scale * 0.9999 ) end
        if not scalePerGroup then for i = 1, #values do 
        	yscales[i] = math.max( unpack( yscales ) ) 
        	yscalesneg[i] = math.max ( 0 , math.max( unpack( yscalesneg ) ) )
        end end
    end

    function tooltip( gi, i, val )
        if tooltips and tooltips[gi] and not nulOrWhitespace( tooltips[gi][i] ) then return tooltips[gi][i], true end
        local groupName = not nulOrWhitespace( groupNames[gi] ) and groupNames[gi] .. ': ' or ''
        local prefix = unitsPrefix[gi] or unitsPrefix[1] or ''
        local suffix = unitsSuffix[gi] or unitsSuffix[1] or ''
        return mw.ustring.gsub(groupName .. prefix .. mw.getContentLanguage():formatNum( tonumber( val ) or 0 ) .. suffix, '_', ' '), false
    end

    function calcHeights( gi, i, val )
    	local barHeight = 0
    	local top, base = 0, 0
    	if  tonumber( val ) >= 0 then
	        barHeight = math.floor( val / ( yscales[gi] + yscalesneg[gi] ) * chartHeight + 0.5 ) -- add half to make it "round" instead of "trunc"
	        top, base = chartHeight - barHeight - yscalesneg[gi] / ( yscales[gi] + yscalesneg[gi] ) * chartHeight , 0
	        -- barHeight = math.floor( val / yscales[gi] * chartHeight + 0.5 ) -- add half to make it "round" instead of "trunc"
        	-- top, base = chartHeight - barHeight, 0
        else 
	        barHeight = math.floor( -val / ( yscales[gi] + yscalesneg[gi] ) * chartHeight + 0.5 ) -- add half to make it "round" instead of "trunc"
	        top, base = chartHeight - yscales[gi] / ( yscales[gi] + yscalesneg[gi] ) * chartHeight, 0
	    end
        if stack then
            local rawbase = 0
            for j = 1, gi - 1 do rawbase = rawbase + values[j][i] end -- sum the "i" value of all the groups below our group, gi.
            base = math.floor( chartHeight * rawbase / yscales[gi] ) -- normally, and especially if it's "stack", all the yscales must be equal.
        end
        return barHeight, top - base
    end
    
    function calcHeightsOld( gi, i, val )
        local barHeight = math.floor( val / yscales[gi] * chartHeight + 0.5 ) -- add half to make it "round" instead of "trunc"
        local top, base = chartHeight - barHeight, 0
        if stack then
            local rawbase = 0
            for j = 1, gi - 1 do rawbase = rawbase + values[j][i] end -- sum the "i" value of all the groups below our group, gi.
            base = math.floor( chartHeight * rawbase / yscales[gi] ) -- normally, and especially if it's "stack", all the yscales must be equal.
        end
        return barHeight, top - base
    end

    function groupBounds( i )
        local setWidth = ( chartWidth / numValues )
        -- local setOffset = ( i - 1 ) * setWidth
        local setOffset = ( i - 1 ) * setWidth
        return setOffset, setWidth
    end

    function calcx( gi, i )
        local setOffset, setWidth = groupBounds( i )
        if stack or numGroups == 1 then
            local barWidth = math.min( 38, ( 0.8 * setWidth ) )
            return setOffset + (setWidth - barWidth) / 2, barWidth
        end
        setWidth = 0.85 * setWidth
        local barWidth = ( 0.75 * setWidth / numGroups )
        local left = setOffset + ( ( gi - 1 ) / numGroups * setWidth )
        return left, barWidth
    end

    function drawbar( gi, i, val, ttval )
        if val == '0' then return end -- do not show single line (borders....) if value is 0, or rather, '0'. see talkpage

        local color, tooltip, custom = colors[gi] or defcolor or 'blue', tooltip( gi, i, ttval or val )
        local left, barWidth = calcx( gi, i )
        local barHeight, top = calcHeights( gi, i, val )
        
        -- borders so it shows up when printing
        local style = string.format("position:absolute;left:%spx;top:%spx;height:%spx;min-width:%spx;max-width:%spx;background-color:%s;-webkit-print-color-adjust:exact;border:1px solid %s;border-bottom:none;overflow:hidden;",
                        left, top, barHeight-1, barWidth-2, barWidth-2, color, color)
        local link = links[gi] and links[gi][i] or ''
        local img = not nulOrWhitespace( link ) and mw.ustring.format( '[[File:Transparent.png|1000px|link=%s|%s]]', link, custom and tooltip or '' ) or ''
        table.insert( res, mw.text.tag( 'div', { style = style, title = tooltip, class = "chart2-bar" }, img ) )
    end





    function drawYScale()
    	
        function drawSingle( gi, color, single )
            local yscale = yscales[gi]
            local _, top, ordermag = roundup( yscale * 0.999 )
            local numnotches = top <= 1.5 and top * 4
                    or top < 4  and top * 2
                    or top
            local valStyleStrCntnr = 'display:block;position:relative;height:%spx;text-align:right;margin:0px;' -- SINGLE ELEMENT OF Y AXIS
            local valStyleStrValue = 'display:block;position:relative;float:right;height:%spx;text-align:right;margin:%spx 0px 0px 0px;vertical-align:middle;line-height:%spx;' -- value
            local valStyleStrNotch = 'display:block;position:relative;float:right;height:%spx;text-align:right;width:5px; border-top:1px solid black' -- notch
                -- or 'position:relative;height=20px;text-align:right;vertical-align:middle;max-width:%spx;top:%spx;left:3px;background-color:%s;color:white;font-weight:bold;text-shadow:-1px -1px 0 #000,1px -1px 0 #000,-1px 1px 0 #000,1px 1px 0 #000;padding:0 2px'
            -- local notchStyleStr = 'position:absolute;height=1px;min-width:5px;top:%spx;left:%spx;border:1px solid %s;'
            for i = 1, numnotches do
                local val = (numnotches - i + 1) / numnotches * yscale -- value of this notch
                
                local y = ( 1 / numnotches * chartHeight )   --chartHeight - calcHeights( gi, 1, val ) -- height of a single notch
                local divCntnr = mw.text.tag( 'div', { style = string.format( valStyleStrCntnr, y, color ) } )
                local divValue = mw.text.tag( 'div', { style = string.format( valStyleStrValue, y, -y/2, y, color ) }, mw.getContentLanguage():formatNum( tonumber( val ) or 0 ) )
                local divNotch = mw.text.tag( 'div', { style = string.format( valStyleStrNotch, y, color ) }, '&nbsp;' ) 
                table.insert( res, divCntnr )
	            if val~=math.floor(val) and optint then
                	
                else
	                table.insert( res, divNotch )
	                table.insert( res, divValue )
            	end
                table.insert( res, '</div>' )
                table.insert( res, '<div style="clear:right;display:block"></div>' )
               
                
                -- div = mw.text.tag( 'div', { style = string.format( notchStyleStr, y, width - 4, color ) }, '' )
                -- table.insert( res, div )
            end
        end

        if scalePerGroup then
            -- local colWidth = 80
            -- local colStyle = "position:absolute;height:%spx;min-width:%spx;left:%spx;border-right:1px solid %s;color:%s"
            
            
            -- local colStyle = "height:%spx;border-right:1px solid %s;color:%s;display:inline-block;text-align:right"
            -- for gi = 1, numGroups do
            --     -- local left = ( gi - 1 ) * colWidth
            --     local color = colors[gi] or defcolor
            --     -- table.insert( res, mw.text.tag( 'div', { style = string.format( colStyle, chartHeight, colWidth, left, color, color ) } ) )
            --     table.insert( res, mw.text.tag( 'div', { style = string.format( colStyle, chartHeight, color, color ) } ) )
            --     drawSingle( gi, color )
            --     table.insert( res, '</div>' )
            -- end
        else
            drawSingle( 1, 'black',  true ) -- gi is the id of y axis when more than 1 
        end
    end




    function drawXlegends()
        local setOffset, setWidth
        local legendDivStyleFormat = "display:block;float:left;position:relative;vertical-align:top;width:%spx;text-align:center;margin:0px 0px 0px %spx;"
        --local tickDivstyleFormat = "display:block;float:left;position:relative;vertical-align:top;border-left:1px solid black;width:%spx;text-align:center;margin:0px 0px 0px %spx;"
        local offsetleft = 0;
        setOffset, setWidth = groupBounds( 1 )
        for i = 1, numValues do
            if not nulOrWhitespace( xlegends[i] ) then
            	--table.insert( res, mw.text.tag( 'div', { style = string.format( tickDivStyleFormat, setWidth/2, offsetleft+setWidth/2 ) }, xlegends[i] or '' ) )
                table.insert( res, mw.text.tag( 'div', { style = string.format( legendDivStyleFormat, setWidth, offsetleft ) }, xlegends[i] or '' ) )
                offsetleft=0;
            else
            	offsetleft=offsetleft+setWidth;
            end
            
                -- setOffset, setWidth = groupBounds( i )
                -- table.insert( res, mw.text.tag( 'div', { style = string.format( legendDivStyleFormat, setWidth ) }, xlegends[i] or '' ) )
            
        end
    end

	function drawXticks()
        local setOffset, setWidth
        local tickDivStyleFormat = "display:block;float:left;position:relative;height:5px;vertical-align:top;border-left:1px solid black;width:%spx;text-align:center;margin:0px 0px 0px %spx;"
        local offsetleft = 0;
        setOffset, setWidth = groupBounds( 1 )
        for i = 1, numValues do
            if not nulOrWhitespace( xlegends[i] ) then
            	table.insert( res, mw.text.tag( 'div', { style = string.format( tickDivStyleFormat, (setWidth/2)-1, (offsetleft+setWidth/2) ) }, '' ) )
                offsetleft=0;
            else
            	offsetleft=offsetleft+setWidth;
            end
        end
    end


    function drawChart()
        table.insert( res, mw.text.tag( 'div', { style = string.format("position:relative;padding:1em 0em 1em 0em;") } ) ) -- container div
        table.insert( res, mw.text.tag( 'div', { style = string.format("position:relative;white-space:nowrap;" ) } ) ) -- container div
		table.insert( res, mw.text.tag( 'div', { style = string.format("position:relative;height:%spx;display:inline-block;text-align:right;vertical-align:top;", chartHeight ) } ) )
        drawYScale()
        table.insert( res, '</div><div style="position:relative;display:inline-block">' )
        -- table.insert( res, mw.text.tag( 'div', { style = string.format("position:relative;display:inline-block" ) } ) ) -- right side container div (should not have space)
        table.insert( res, mw.text.tag( 'div', { style = string.format("height:%spx;width:%spx;border-left:1px black solid;border-bottom:1px black solid;display:block;margin:0px;padding:0px;", chartHeight, chartWidth ) } ) ) -- the actual chart
        local acum = stack and accumulateTooltip and {}
        for gi, group in pairs( values ) do
            for i, val in ipairs( group ) do
                if acum then acum[i] = ( acum[i] or 0 ) + val end
                drawbar( gi, i, val, acum and acum[i] )
            end
        end
        table.insert( res, '</div>' )
        table.insert( res, mw.text.tag( 'div', { style = string.format( "position:relative;width:%spx;float:left;", chartWidth ) } ) ) -- X ticks
        drawXticks()
        table.insert( res, '</div>' )
        table.insert( res, mw.text.tag( 'div', { style = string.format( "position:relative;width:%spx;", chartWidth ) } ) ) -- X legends
        drawXlegends()
        table.insert( res, '</div>' )
        table.insert( res, '</div>' )
        table.insert( res, '</div>' )
        createGroupList( res, groupNames, colors )
        table.insert( res, '</div>' )
    end

    extractParams()
    validate()
    calcHeightLimits()
    drawChart()
    return table.concat( res, "\n" )
end

return {
    ['bar-chart'] = barChart,
    [keywords.barChart] = barChart,
    [keywords.pieChart] = pieChart,
}
--</source>