peity_vanilla_rails 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +11 -12
- data/app/assets/javascripts/peity-vanilla-rails.esm.js +503 -0
- data/app/assets/javascripts/peity-vanilla-rails.min.js +11 -0
- data/app/assets/javascripts/peity-vanilla.esm.js +421 -0
- data/app/assets/javascripts/peity-vanilla.min.js +6 -0
- data/config/importmap.rb +2 -1
- data/lib/peity_vanilla_rails/engine.rb +2 -7
- data/lib/peity_vanilla_rails/helpers.rb +14 -38
- data/lib/peity_vanilla_rails/version.rb +1 -1
- metadata +7 -6
- data/app/assets/javascripts/peity_vanilla.esm.js +0 -376
- data/app/assets/javascripts/peity_vanilla.js +0 -385
- data/app/assets/javascripts/peity_vanilla.js.map +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 53261d4741de90d14704c23e23624151184465c0e1a57edcd00b32b6751167e5
|
4
|
+
data.tar.gz: f7215991dffe2cc9756842981d36714b72c779cf7fabf9f3e522fda478b2a42d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 38eb290c3931f3fcb6ddb0b0397e039793a15b1475915839b02575640b413cd48fecd97b0e327cfe8cf4992096af73c9e6c645fee297525bcf01e7792f0d00c6
|
7
|
+
data.tar.gz: ca345ad7e083cb26559c9605235718795e81a374ea819e6349f09f239475c254c028cc22ba3ebd7bdb94d7656edfa1c465427a87d46b4a4a73e5a3498f743a9b
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
[](https://www.railsjazz.com)
|
4
4
|
|
5
|
-
Sparklines are small but intense charts. This gem is a wrapper around [
|
5
|
+
Sparklines are small but intense charts. This gem is a wrapper around [peity-vanilla](https://github.com/railsjazz/peity_vanilla) library. You can generate simple but informative charts with vanilla JS.
|
6
6
|
|
7
7
|
<img src="./docs/sparklines.png" height="400px"/>
|
8
8
|
|
@@ -19,7 +19,7 @@ gem "peity_vanilla_rails"
|
|
19
19
|
### For Assets Pipeline:
|
20
20
|
|
21
21
|
```javascript
|
22
|
-
//= require
|
22
|
+
//= require peity-vanilla-rails.js
|
23
23
|
```
|
24
24
|
|
25
25
|
### For Importmaps
|
@@ -27,11 +27,12 @@ gem "peity_vanilla_rails"
|
|
27
27
|
In `application.js`
|
28
28
|
|
29
29
|
```js
|
30
|
-
import
|
31
|
-
|
32
|
-
window.peity = peity;
|
30
|
+
import "peity-vanilla-rails";
|
33
31
|
```
|
34
32
|
|
33
|
+
#### Note: After `peity-vanilla-rails.js` is imported, it will listen to changes of `peity` and `data-peity` attributes of every DOM element
|
34
|
+
Pure `peity-vanilla` library is also acessible via `peity-vanilla.js` for Assets Pipeline, and `import peity from "peity-vanilla"` for Importmaps
|
35
|
+
|
35
36
|
3. Add charts in your code:
|
36
37
|
|
37
38
|
```erb
|
@@ -64,20 +65,19 @@ Check the [original](https://github.com/railsjazz/peity_vanilla) page.
|
|
64
65
|
<img src="https://github.com/railsjazz/peity_vanilla/raw/main/docs/custom.png"/>
|
65
66
|
<img src="https://github.com/railsjazz/peity_vanilla/raw/main/docs/animation.gif"/>
|
66
67
|
|
67
|
-
```
|
68
|
-
|
68
|
+
```erb
|
69
|
+
<%= peity_line_chart([5,3,9,6,5,9,7,3,5,2,5,3,9,6,5,9,7,3,5,2], id: 'updating-chart') %>
|
69
70
|
|
70
71
|
<script>
|
71
|
-
var updatingChart =
|
72
|
+
var updatingChart = document.getElementById("updating-chart");
|
72
73
|
|
73
74
|
setInterval(function() {
|
74
75
|
var random = Math.round(Math.random() * 10)
|
75
|
-
var values = updatingChart.
|
76
|
+
var values = updatingChart.innerText.split(",")
|
76
77
|
values.shift()
|
77
78
|
values.push(random)
|
78
79
|
|
79
|
-
updatingChart.
|
80
|
-
updatingChart.element.dispatchEvent(new Event('change'))
|
80
|
+
updatingChart.innerText = values.join(",")
|
81
81
|
}, 1000);
|
82
82
|
</script>
|
83
83
|
```
|
@@ -132,7 +132,6 @@ You can pass in `options` any of the attributes.
|
|
132
132
|
|
133
133
|
## TODO
|
134
134
|
|
135
|
-
- stimulus, turbo, etc.
|
136
135
|
- remote datasource and autoupdate
|
137
136
|
|
138
137
|
## Contributing
|
@@ -0,0 +1,503 @@
|
|
1
|
+
/*!
|
2
|
+
Peity Vanila Rails 0.2.0
|
3
|
+
Copyright © 2022 RailsJazz
|
4
|
+
https://railsjazz.com
|
5
|
+
*/
|
6
|
+
|
7
|
+
/*!
|
8
|
+
Peity Vanila JS 0.0.8
|
9
|
+
Copyright © 2022 RailsJazz
|
10
|
+
https://railsjazz.com
|
11
|
+
*/
|
12
|
+
|
13
|
+
const isFunction = (o) =>
|
14
|
+
o !== null && typeof o === "function" && !!o.apply;
|
15
|
+
|
16
|
+
const svgElement = (tag, attrs) => {
|
17
|
+
const element = document.createElementNS("http://www.w3.org/2000/svg", tag);
|
18
|
+
for (var attr in attrs) {
|
19
|
+
element.setAttribute(attr, attrs[attr]);
|
20
|
+
}
|
21
|
+
return element;
|
22
|
+
};
|
23
|
+
|
24
|
+
const svgSupported =
|
25
|
+
"createElementNS" in document && svgElement("svg", {}).createSVGRect();
|
26
|
+
|
27
|
+
class Peity {
|
28
|
+
static defaults = {};
|
29
|
+
static graphers = {};
|
30
|
+
|
31
|
+
constructor(element, type, options = {}) {
|
32
|
+
this.element = element;
|
33
|
+
this.type = type;
|
34
|
+
this.options = Object.assign(
|
35
|
+
{},
|
36
|
+
Peity.defaults[this.type],
|
37
|
+
JSON.parse(element.dataset["peity"] || "{}"),
|
38
|
+
options
|
39
|
+
);
|
40
|
+
|
41
|
+
if(this.element._peity) {
|
42
|
+
this.element._peity.destroy();
|
43
|
+
}
|
44
|
+
this.element._peity = this;
|
45
|
+
}
|
46
|
+
|
47
|
+
draw() {
|
48
|
+
const options = this.options;
|
49
|
+
Peity.graphers[this.type](this);
|
50
|
+
if (isFunction(options.after)) options.after.call(this, options);
|
51
|
+
}
|
52
|
+
|
53
|
+
fill() {
|
54
|
+
var fill = this.options.fill;
|
55
|
+
|
56
|
+
return isFunction(fill)
|
57
|
+
? fill
|
58
|
+
: function (_, i) {
|
59
|
+
return fill[i % fill.length];
|
60
|
+
};
|
61
|
+
}
|
62
|
+
|
63
|
+
prepare(width, height) {
|
64
|
+
if (!this.svg) {
|
65
|
+
this.element.style.display = "none";
|
66
|
+
this.element.after(
|
67
|
+
(this.svg = svgElement("svg", {
|
68
|
+
class: "peity",
|
69
|
+
}))
|
70
|
+
);
|
71
|
+
}
|
72
|
+
|
73
|
+
this.svg.innerHTML = "";
|
74
|
+
this.svg.setAttribute("width", width);
|
75
|
+
this.svg.setAttribute("height", height);
|
76
|
+
|
77
|
+
return this.svg;
|
78
|
+
}
|
79
|
+
|
80
|
+
get values() {
|
81
|
+
return this.element.innerText
|
82
|
+
.split(this.options.delimiter)
|
83
|
+
.map((value) => parseFloat(value));
|
84
|
+
}
|
85
|
+
|
86
|
+
mount() {
|
87
|
+
if (!svgSupported) return;
|
88
|
+
|
89
|
+
this.element.addEventListener("DOMSubtreeModified", this.draw.bind(this));
|
90
|
+
this.draw();
|
91
|
+
|
92
|
+
this.mounted = true;
|
93
|
+
}
|
94
|
+
|
95
|
+
unmount() {
|
96
|
+
this.element.removeEventListener("DOMSubtreeModified", this.draw);
|
97
|
+
this.svg.remove();
|
98
|
+
this.mounted = false;
|
99
|
+
}
|
100
|
+
|
101
|
+
destroy() {
|
102
|
+
this.unmount();
|
103
|
+
|
104
|
+
delete this.element._peity;
|
105
|
+
}
|
106
|
+
|
107
|
+
static register(type, defaults, grapher) {
|
108
|
+
Peity.defaults[type] = defaults;
|
109
|
+
Peity.graphers[type] = grapher;
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
const renderer$2 = (peity) => {
|
114
|
+
if (!peity.options.delimiter) {
|
115
|
+
const delimiter = peity.element.innerText.match(/[^0-9\.]/);
|
116
|
+
peity.options.delimiter = delimiter ? delimiter[0] : ",";
|
117
|
+
}
|
118
|
+
|
119
|
+
let values = peity.values.map((n) => (n > 0 ? n : 0));
|
120
|
+
|
121
|
+
if (peity.options.delimiter == "/") {
|
122
|
+
let v1 = values[0];
|
123
|
+
let v2 = values[1];
|
124
|
+
values = [v1, Math.max(0, v2 - v1)];
|
125
|
+
}
|
126
|
+
|
127
|
+
let i = 0;
|
128
|
+
let length = values.length;
|
129
|
+
let sum = 0;
|
130
|
+
|
131
|
+
for (; i < length; i++) {
|
132
|
+
sum += values[i];
|
133
|
+
}
|
134
|
+
|
135
|
+
if (!sum) {
|
136
|
+
length = 2;
|
137
|
+
sum = 1;
|
138
|
+
values = [0, 1];
|
139
|
+
}
|
140
|
+
|
141
|
+
let diameter = peity.options.radius * 2;
|
142
|
+
|
143
|
+
const svg = peity.prepare(
|
144
|
+
peity.options.width || diameter,
|
145
|
+
peity.options.height || diameter
|
146
|
+
);
|
147
|
+
|
148
|
+
const width = svg.clientWidth;
|
149
|
+
const height = svg.clientHeight;
|
150
|
+
const cx = width / 2;
|
151
|
+
const cy = height / 2;
|
152
|
+
|
153
|
+
const radius = Math.min(cx, cy);
|
154
|
+
let innerRadius = peity.options.innerRadius;
|
155
|
+
|
156
|
+
if (peity.type == "donut" && !innerRadius) {
|
157
|
+
innerRadius = radius * 0.5;
|
158
|
+
}
|
159
|
+
|
160
|
+
const fill = peity.fill();
|
161
|
+
|
162
|
+
const scale = (value, radius) => {
|
163
|
+
const radians = (value / sum) * Math.PI * 2 - Math.PI / 2;
|
164
|
+
|
165
|
+
return [radius * Math.cos(radians) + cx, radius * Math.sin(radians) + cy];
|
166
|
+
};
|
167
|
+
|
168
|
+
let cumulative = 0;
|
169
|
+
|
170
|
+
for (i = 0; i < length; i++) {
|
171
|
+
const value = values[i];
|
172
|
+
const portion = value / sum;
|
173
|
+
let node;
|
174
|
+
|
175
|
+
if (portion == 0) continue;
|
176
|
+
|
177
|
+
if (portion == 1) {
|
178
|
+
if (innerRadius) {
|
179
|
+
const x2 = cx - 0.01;
|
180
|
+
const y1 = cy - radius;
|
181
|
+
const y2 = cy - innerRadius;
|
182
|
+
|
183
|
+
node = svgElement("path", {
|
184
|
+
d: [
|
185
|
+
"M",
|
186
|
+
cx,
|
187
|
+
y1,
|
188
|
+
"A",
|
189
|
+
radius,
|
190
|
+
radius,
|
191
|
+
0,
|
192
|
+
1,
|
193
|
+
1,
|
194
|
+
x2,
|
195
|
+
y1,
|
196
|
+
"L",
|
197
|
+
x2,
|
198
|
+
y2,
|
199
|
+
"A",
|
200
|
+
innerRadius,
|
201
|
+
innerRadius,
|
202
|
+
0,
|
203
|
+
1,
|
204
|
+
0,
|
205
|
+
cx,
|
206
|
+
y2,
|
207
|
+
].join(" "),
|
208
|
+
"data-value": value,
|
209
|
+
});
|
210
|
+
} else {
|
211
|
+
node = svgElement("circle", {
|
212
|
+
cx: cx,
|
213
|
+
cy: cy,
|
214
|
+
"data-value": value,
|
215
|
+
r: radius,
|
216
|
+
});
|
217
|
+
}
|
218
|
+
} else {
|
219
|
+
const cumulativePlusValue = cumulative + value;
|
220
|
+
|
221
|
+
let d = ["M"].concat(
|
222
|
+
scale(cumulative, radius),
|
223
|
+
"A",
|
224
|
+
radius,
|
225
|
+
radius,
|
226
|
+
0,
|
227
|
+
portion > 0.5 ? 1 : 0,
|
228
|
+
1,
|
229
|
+
scale(cumulativePlusValue, radius),
|
230
|
+
"L"
|
231
|
+
);
|
232
|
+
|
233
|
+
if (innerRadius) {
|
234
|
+
d = d.concat(
|
235
|
+
scale(cumulativePlusValue, innerRadius),
|
236
|
+
"A",
|
237
|
+
innerRadius,
|
238
|
+
innerRadius,
|
239
|
+
0,
|
240
|
+
portion > 0.5 ? 1 : 0,
|
241
|
+
0,
|
242
|
+
scale(cumulative, innerRadius)
|
243
|
+
);
|
244
|
+
} else {
|
245
|
+
d.push(cx, cy);
|
246
|
+
}
|
247
|
+
|
248
|
+
cumulative += value;
|
249
|
+
|
250
|
+
node = svgElement("path", {
|
251
|
+
d: d.join(" "),
|
252
|
+
"data-value": value,
|
253
|
+
});
|
254
|
+
}
|
255
|
+
|
256
|
+
node.setAttribute("fill", fill.call(peity, value, i, values));
|
257
|
+
|
258
|
+
svg.append(node);
|
259
|
+
}
|
260
|
+
};
|
261
|
+
|
262
|
+
const defaults$2 = {
|
263
|
+
fill: ["#ff9900", "#fff4dd", "#ffc66e"],
|
264
|
+
radius: 8,
|
265
|
+
};
|
266
|
+
|
267
|
+
const renderer$1 = (peity) => {
|
268
|
+
const values = peity.values;
|
269
|
+
const max = Math.max.apply(
|
270
|
+
Math,
|
271
|
+
peity.options.max == undefined ? values : values.concat(peity.options.max)
|
272
|
+
);
|
273
|
+
const min = Math.min.apply(
|
274
|
+
Math,
|
275
|
+
peity.options.min == undefined ? values : values.concat(peity.options.min)
|
276
|
+
);
|
277
|
+
|
278
|
+
const svg = peity.prepare(peity.options.width, peity.options.height);
|
279
|
+
const width = svg.clientWidth;
|
280
|
+
const height = svg.clientHeight;
|
281
|
+
const diff = max - min;
|
282
|
+
const padding = peity.options.padding;
|
283
|
+
const fill = peity.fill();
|
284
|
+
|
285
|
+
const xScale = (input) => {
|
286
|
+
return (input * width) / values.length;
|
287
|
+
};
|
288
|
+
|
289
|
+
const yScale = (input) => {
|
290
|
+
return height - (diff ? ((input - min) / diff) * height : 1);
|
291
|
+
};
|
292
|
+
|
293
|
+
for (var i = 0; i < values.length; i++) {
|
294
|
+
let x = xScale(i + padding);
|
295
|
+
let w = xScale(i + 1 - padding) - x;
|
296
|
+
let value = values[i];
|
297
|
+
let valueY = yScale(value);
|
298
|
+
let y1 = valueY;
|
299
|
+
let y2 = valueY;
|
300
|
+
let h;
|
301
|
+
|
302
|
+
if (!diff) {
|
303
|
+
h = 1;
|
304
|
+
} else if (value < 0) {
|
305
|
+
y1 = yScale(Math.min(max, 0));
|
306
|
+
} else {
|
307
|
+
y2 = yScale(Math.max(min, 0));
|
308
|
+
}
|
309
|
+
|
310
|
+
h = y2 - y1;
|
311
|
+
|
312
|
+
if (h == 0) {
|
313
|
+
h = 1;
|
314
|
+
if (max > 0 && diff) y1--;
|
315
|
+
}
|
316
|
+
|
317
|
+
svg.append(
|
318
|
+
svgElement("rect", {
|
319
|
+
"data-value": value,
|
320
|
+
fill: fill.call(peity, value, i, values),
|
321
|
+
x: x,
|
322
|
+
y: y1,
|
323
|
+
width: w,
|
324
|
+
height: h,
|
325
|
+
})
|
326
|
+
);
|
327
|
+
}
|
328
|
+
};
|
329
|
+
|
330
|
+
const defaults$1 = {
|
331
|
+
delimiter: ",",
|
332
|
+
fill: ["#4D89F9"],
|
333
|
+
height: 16,
|
334
|
+
min: 0,
|
335
|
+
padding: 0.1,
|
336
|
+
width: 32,
|
337
|
+
};
|
338
|
+
|
339
|
+
const renderer = (peity) => {
|
340
|
+
const values = peity.values;
|
341
|
+
if (values.length == 1) values.push(values[0]);
|
342
|
+
const max = Math.max.apply(
|
343
|
+
Math,
|
344
|
+
peity.options.max == undefined ? values : values.concat(peity.options.max)
|
345
|
+
);
|
346
|
+
const min = Math.min.apply(
|
347
|
+
Math,
|
348
|
+
peity.options.min == undefined ? values : values.concat(peity.options.min)
|
349
|
+
);
|
350
|
+
|
351
|
+
const svg = peity.prepare(peity.options.width, peity.options.height);
|
352
|
+
const strokeWidth = peity.options.strokeWidth;
|
353
|
+
const width = svg.clientWidth;
|
354
|
+
const height = svg.clientHeight - strokeWidth;
|
355
|
+
const diff = max - min;
|
356
|
+
|
357
|
+
const xScale = (input) => {
|
358
|
+
return input * (width / (values.length - 1));
|
359
|
+
};
|
360
|
+
|
361
|
+
const yScale = (input) => {
|
362
|
+
let y = height;
|
363
|
+
|
364
|
+
if (diff) {
|
365
|
+
y -= ((input - min) / diff) * height;
|
366
|
+
}
|
367
|
+
|
368
|
+
return y + strokeWidth / 2;
|
369
|
+
};
|
370
|
+
|
371
|
+
let zero = yScale(Math.max(min, 0));
|
372
|
+
let coords = [0, zero];
|
373
|
+
|
374
|
+
for (var i = 0; i < values.length; i++) {
|
375
|
+
coords.push(xScale(i), yScale(values[i]));
|
376
|
+
}
|
377
|
+
|
378
|
+
coords.push(width, zero);
|
379
|
+
|
380
|
+
if (peity.options.fill) {
|
381
|
+
svg.append(
|
382
|
+
svgElement("polygon", {
|
383
|
+
fill: peity.options.fill,
|
384
|
+
points: coords.join(" "),
|
385
|
+
})
|
386
|
+
);
|
387
|
+
}
|
388
|
+
|
389
|
+
if (strokeWidth) {
|
390
|
+
svg.append(
|
391
|
+
svgElement("polyline", {
|
392
|
+
fill: "none",
|
393
|
+
points: coords.slice(2, coords.length - 2).join(" "),
|
394
|
+
stroke: peity.options.stroke,
|
395
|
+
"stroke-width": strokeWidth,
|
396
|
+
"stroke-linecap": "square",
|
397
|
+
})
|
398
|
+
);
|
399
|
+
}
|
400
|
+
};
|
401
|
+
|
402
|
+
const defaults = {
|
403
|
+
delimiter: ",",
|
404
|
+
fill: "#c6d9fd",
|
405
|
+
height: 16,
|
406
|
+
min: 0,
|
407
|
+
stroke: "#4d89f9",
|
408
|
+
strokeWidth: 1,
|
409
|
+
width: 32,
|
410
|
+
};
|
411
|
+
|
412
|
+
Peity.register("pie", defaults$2, renderer$2);
|
413
|
+
Peity.register("donut", defaults$2, renderer$2);
|
414
|
+
Peity.register("bar", defaults$1, renderer$1);
|
415
|
+
Peity.register("line", defaults, renderer);
|
416
|
+
|
417
|
+
const peity = function (element, type, options) {
|
418
|
+
const peity = new Peity(element, type, options);
|
419
|
+
peity.mount();
|
420
|
+
|
421
|
+
return peity;
|
422
|
+
};
|
423
|
+
|
424
|
+
peity.defaults = Peity.defaults;
|
425
|
+
peity.graphers = Peity.graphers;
|
426
|
+
|
427
|
+
const getPeityType = (node) => node.getAttribute('peity');
|
428
|
+
|
429
|
+
const elementFromNode = (node) => {
|
430
|
+
if (node.nodeType == Node.ELEMENT_NODE) {
|
431
|
+
return node;
|
432
|
+
}
|
433
|
+
};
|
434
|
+
|
435
|
+
const processNodeAdded = (node) => {
|
436
|
+
if (node.matches("[peity]")) {
|
437
|
+
peity(node, getPeityType(node));
|
438
|
+
}
|
439
|
+
};
|
440
|
+
|
441
|
+
const processNodeRemoved = (node) => {
|
442
|
+
if (node._peity) {
|
443
|
+
node._peity.destroy();
|
444
|
+
}
|
445
|
+
};
|
446
|
+
|
447
|
+
const processAttributeChanged = (mutation) => {
|
448
|
+
const node = mutation.target;
|
449
|
+
switch (mutation.attributeName) {
|
450
|
+
case "peity":
|
451
|
+
const type = getPeityType(node);
|
452
|
+
if (type) {
|
453
|
+
peity(node, type);
|
454
|
+
} else {
|
455
|
+
node._peity.unmount();
|
456
|
+
}
|
457
|
+
break;
|
458
|
+
case "data-peity":
|
459
|
+
if(node._peity) {
|
460
|
+
peity(node, node._peity.type);
|
461
|
+
}
|
462
|
+
break;
|
463
|
+
}
|
464
|
+
};
|
465
|
+
|
466
|
+
const callback = (mutationList, observer) => {
|
467
|
+
mutationList.forEach(function (mutation) {
|
468
|
+
switch (mutation.type) {
|
469
|
+
case "childList":
|
470
|
+
for (const node of Array.from(mutation.addedNodes)) {
|
471
|
+
const element = elementFromNode(node);
|
472
|
+
if (element) {
|
473
|
+
processNodeAdded(element);
|
474
|
+
}
|
475
|
+
}
|
476
|
+
for (const node of Array.from(mutation.removedNodes)) {
|
477
|
+
const element = elementFromNode(node);
|
478
|
+
if (element) {
|
479
|
+
processNodeRemoved(element);
|
480
|
+
}
|
481
|
+
}
|
482
|
+
break;
|
483
|
+
case "attributes":
|
484
|
+
processAttributeChanged(mutation);
|
485
|
+
break;
|
486
|
+
}
|
487
|
+
});
|
488
|
+
};
|
489
|
+
|
490
|
+
const observerOptions = {
|
491
|
+
childList: true,
|
492
|
+
attributes: true,
|
493
|
+
subtree: true,
|
494
|
+
};
|
495
|
+
|
496
|
+
const observer = new MutationObserver(callback);
|
497
|
+
observer.observe(document.documentElement, observerOptions);
|
498
|
+
|
499
|
+
for (const node of Array.from(document.documentElement.querySelectorAll('[peity]'))) {
|
500
|
+
processNodeAdded(node);
|
501
|
+
}
|
502
|
+
|
503
|
+
export { peity as default };
|
@@ -0,0 +1,11 @@
|
|
1
|
+
/*!
|
2
|
+
Peity Vanila Rails 0.2.0
|
3
|
+
Copyright © 2022 RailsJazz
|
4
|
+
https://railsjazz.com
|
5
|
+
*/
|
6
|
+
var peity=function(){"use strict";
|
7
|
+
/*!
|
8
|
+
Peity Vanila JS 0.0.8
|
9
|
+
Copyright © 2022 RailsJazz
|
10
|
+
https://railsjazz.com
|
11
|
+
*/const t=t=>null!==t&&"function"==typeof t&&!!t.apply,e=(t,e)=>{const i=document.createElementNS("http://www.w3.org/2000/svg",t);for(var n in e)i.setAttribute(n,e[n]);return i},i="createElementNS"in document&&e("svg",{}).createSVGRect();class n{static defaults={};static graphers={};constructor(t,e,i={}){this.element=t,this.type=e,this.options=Object.assign({},n.defaults[this.type],JSON.parse(t.dataset.peity||"{}"),i),this.element._peity&&this.element._peity.destroy(),this.element._peity=this}draw(){const e=this.options;n.graphers[this.type](this),t(e.after)&&e.after.call(this,e)}fill(){var e=this.options.fill;return t(e)?e:function(t,i){return e[i%e.length]}}prepare(t,i){return this.svg||(this.element.style.display="none",this.element.after(this.svg=e("svg",{class:"peity"}))),this.svg.innerHTML="",this.svg.setAttribute("width",t),this.svg.setAttribute("height",i),this.svg}get values(){return this.element.innerText.split(this.options.delimiter).map((t=>parseFloat(t)))}mount(){i&&(this.element.addEventListener("DOMSubtreeModified",this.draw.bind(this)),this.draw(),this.mounted=!0)}unmount(){this.element.removeEventListener("DOMSubtreeModified",this.draw),this.svg.remove(),this.mounted=!1}destroy(){this.unmount(),delete this.element._peity}static register(t,e,i){n.defaults[t]=e,n.graphers[t]=i}}const s=t=>{if(!t.options.delimiter){const e=t.element.innerText.match(/[^0-9\.]/);t.options.delimiter=e?e[0]:","}let i=t.values.map((t=>t>0?t:0));if("/"==t.options.delimiter){let t=i[0],e=i[1];i=[t,Math.max(0,e-t)]}let n=0,s=i.length,o=0;for(;n<s;n++)o+=i[n];o||(s=2,o=1,i=[0,1]);let r=2*t.options.radius;const a=t.prepare(t.options.width||r,t.options.height||r),l=a.clientWidth,h=a.clientHeight,p=l/2,c=h/2,d=Math.min(p,c);let u=t.options.innerRadius;"donut"!=t.type||u||(u=.5*d);const m=t.fill(),f=(t,e)=>{const i=t/o*Math.PI*2-Math.PI/2;return[e*Math.cos(i)+p,e*Math.sin(i)+c]};let g=0;for(n=0;n<s;n++){const s=i[n],r=s/o;let l;if(0!=r){if(1==r)if(u){const t=p-.01,i=c-d,n=c-u;l=e("path",{d:["M",p,i,"A",d,d,0,1,1,t,i,"L",t,n,"A",u,u,0,1,0,p,n].join(" "),"data-value":s})}else l=e("circle",{cx:p,cy:c,"data-value":s,r:d});else{const t=g+s;let i=["M"].concat(f(g,d),"A",d,d,0,r>.5?1:0,1,f(t,d),"L");u?i=i.concat(f(t,u),"A",u,u,0,r>.5?1:0,0,f(g,u)):i.push(p,c),g+=s,l=e("path",{d:i.join(" "),"data-value":s})}l.setAttribute("fill",m.call(t,s,n,i)),a.append(l)}}},o={fill:["#ff9900","#fff4dd","#ffc66e"],radius:8};n.register("pie",o,s),n.register("donut",o,s),n.register("bar",{delimiter:",",fill:["#4D89F9"],height:16,min:0,padding:.1,width:32},(t=>{const i=t.values,n=Math.max.apply(Math,null==t.options.max?i:i.concat(t.options.max)),s=Math.min.apply(Math,null==t.options.min?i:i.concat(t.options.min)),o=t.prepare(t.options.width,t.options.height),r=o.clientWidth,a=o.clientHeight,l=n-s,h=t.options.padding,p=t.fill(),c=t=>t*r/i.length,d=t=>a-(l?(t-s)/l*a:1);for(var u=0;u<i.length;u++){let r,a=c(u+h),m=c(u+1-h)-a,f=i[u],g=d(f),y=g,v=g;l?f<0?y=d(Math.min(n,0)):v=d(Math.max(s,0)):r=1,r=v-y,0==r&&(r=1,n>0&&l&&y--),o.append(e("rect",{"data-value":f,fill:p.call(t,f,u,i),x:a,y:y,width:m,height:r}))}})),n.register("line",{delimiter:",",fill:"#c6d9fd",height:16,min:0,stroke:"#4d89f9",strokeWidth:1,width:32},(t=>{const i=t.values;1==i.length&&i.push(i[0]);const n=Math.max.apply(Math,null==t.options.max?i:i.concat(t.options.max)),s=Math.min.apply(Math,null==t.options.min?i:i.concat(t.options.min)),o=t.prepare(t.options.width,t.options.height),r=t.options.strokeWidth,a=o.clientWidth,l=o.clientHeight-r,h=n-s,p=t=>{let e=l;return h&&(e-=(t-s)/h*l),e+r/2};let c=p(Math.max(s,0)),d=[0,c];for(var u=0;u<i.length;u++)d.push(u*(a/(i.length-1)),p(i[u]));d.push(a,c),t.options.fill&&o.append(e("polygon",{fill:t.options.fill,points:d.join(" ")})),r&&o.append(e("polyline",{fill:"none",points:d.slice(2,d.length-2).join(" "),stroke:t.options.stroke,"stroke-width":r,"stroke-linecap":"square"}))}));const r=function(t,e,i){const s=new n(t,e,i);return s.mount(),s};r.defaults=n.defaults,r.graphers=n.graphers;const a=t=>t.getAttribute("peity"),l=t=>{if(t.nodeType==Node.ELEMENT_NODE)return t},h=t=>{t.matches("[peity]")&&r(t,a(t))},p=t=>{t._peity&&t._peity.destroy()};new MutationObserver(((t,e)=>{t.forEach((function(t){switch(t.type){case"childList":for(const e of Array.from(t.addedNodes)){const t=l(e);t&&h(t)}for(const e of Array.from(t.removedNodes)){const t=l(e);t&&p(t)}break;case"attributes":(t=>{const e=t.target;switch(t.attributeName){case"peity":const t=a(e);t?r(e,t):e._peity.unmount();break;case"data-peity":e._peity&&r(e,e._peity.type)}})(t)}}))})).observe(document.documentElement,{childList:!0,attributes:!0,subtree:!0});for(const t of Array.from(document.documentElement.querySelectorAll("[peity]")))h(t);return r}();
|