peity_vanilla_rails 0.1.1 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +24 -8
- data/app/assets/javascripts/peity-vanilla-rails.esm.js +519 -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 -0
- data/lib/peity_vanilla_rails/engine.rb +3 -8
- data/lib/peity_vanilla_rails/helpers.rb +14 -38
- data/lib/peity_vanilla_rails/version.rb +1 -1
- metadata +11 -5
- data/app/assets/javascripts/peity_vanilla.js +0 -317
- 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: de5631424fd3980ed3c9c8a7e02a4c7e10cc77650ebdea1f8d17cb99d526ca96
|
4
|
+
data.tar.gz: 85a1ae8f2d6e05fad50d5362c0ce3c55d8e0b8d04354d028cf247562a76194a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a90b637c07453922d6ad43cff0def5c8daa35fcdd4c0e094acd053f6e85226fab91a5f606efc434fe9144ed676993a2ebe95582ad8420aca182cf6e987674054
|
7
|
+
data.tar.gz: 0b2a6938fd2ab60492f943965a8a45e128f31098d262ec5315a9e3252daa257b40be98728dee23402192ac5bd485069d839cfa080102126af39d711aa870c4ec
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# Peity Vanilla Rails
|
2
2
|
|
3
|
-
|
3
|
+
[![RailsJazz](https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/my_other.svg?raw=true)](https://www.railsjazz.com)
|
4
|
+
|
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.
|
4
6
|
|
5
7
|
<img src="./docs/sparklines.png" height="400px"/>
|
6
8
|
|
@@ -14,10 +16,23 @@ gem "peity_vanilla_rails"
|
|
14
16
|
|
15
17
|
2. Add to `application.js`
|
16
18
|
|
19
|
+
### For Assets Pipeline:
|
20
|
+
|
17
21
|
```javascript
|
18
|
-
//= require
|
22
|
+
//= require peity-vanilla-rails.js
|
23
|
+
```
|
24
|
+
|
25
|
+
### For Importmaps
|
26
|
+
|
27
|
+
In `application.js`
|
28
|
+
|
29
|
+
```js
|
30
|
+
import "peity-vanilla-rails";
|
19
31
|
```
|
20
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
|
+
|
21
36
|
3. Add charts in your code:
|
22
37
|
|
23
38
|
```erb
|
@@ -50,21 +65,19 @@ Check the [original](https://github.com/railsjazz/peity_vanilla) page.
|
|
50
65
|
<img src="https://github.com/railsjazz/peity_vanilla/raw/main/docs/custom.png"/>
|
51
66
|
<img src="https://github.com/railsjazz/peity_vanilla/raw/main/docs/animation.gif"/>
|
52
67
|
|
53
|
-
```
|
54
|
-
|
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') %>
|
55
70
|
|
56
71
|
<script>
|
57
|
-
var updatingChart =
|
72
|
+
var updatingChart = document.getElementById("updating-chart");
|
58
73
|
|
59
74
|
setInterval(function() {
|
60
75
|
var random = Math.round(Math.random() * 10)
|
61
|
-
// debugger
|
62
76
|
var values = updatingChart.innerText.split(",")
|
63
77
|
values.shift()
|
64
78
|
values.push(random)
|
65
79
|
|
66
80
|
updatingChart.innerText = values.join(",")
|
67
|
-
updatingChart.dispatchEvent(new Event('change'))
|
68
81
|
}, 1000);
|
69
82
|
</script>
|
70
83
|
```
|
@@ -119,7 +132,6 @@ You can pass in `options` any of the attributes.
|
|
119
132
|
|
120
133
|
## TODO
|
121
134
|
|
122
|
-
- stimulus, turbo, etc.
|
123
135
|
- remote datasource and autoupdate
|
124
136
|
|
125
137
|
## Contributing
|
@@ -129,3 +141,7 @@ You are welcome to contribute.
|
|
129
141
|
## License
|
130
142
|
|
131
143
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
144
|
+
|
145
|
+
|
146
|
+
[<img src="https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/more_gems.png?raw=true"
|
147
|
+
/>](https://www.railsjazz.com/?utm_source=github&utm_medium=bottom&utm_campaign=peity_vanilla_rails)
|
@@ -0,0 +1,519 @@
|
|
1
|
+
/*!
|
2
|
+
Peity Vanila Rails 0.2.1
|
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
|
+
function domReady() {
|
428
|
+
return new Promise((resolve) => {
|
429
|
+
if (document.readyState == "loading") {
|
430
|
+
document.addEventListener("DOMContentLoaded", resolve);
|
431
|
+
} else {
|
432
|
+
resolve();
|
433
|
+
}
|
434
|
+
});
|
435
|
+
}
|
436
|
+
|
437
|
+
const getPeityType = (node) => node.getAttribute("peity");
|
438
|
+
|
439
|
+
const elementFromNode = (node) => {
|
440
|
+
if (node.nodeType == Node.ELEMENT_NODE) {
|
441
|
+
return node;
|
442
|
+
}
|
443
|
+
};
|
444
|
+
|
445
|
+
const processNodeAdded = (node) => {
|
446
|
+
if (node.matches("[peity]")) {
|
447
|
+
peity(node, getPeityType(node));
|
448
|
+
}
|
449
|
+
};
|
450
|
+
|
451
|
+
const processNodeRemoved = (node) => {
|
452
|
+
if (node._peity) {
|
453
|
+
node._peity.destroy();
|
454
|
+
}
|
455
|
+
};
|
456
|
+
|
457
|
+
const processAttributeChanged = (mutation) => {
|
458
|
+
const node = mutation.target;
|
459
|
+
switch (mutation.attributeName) {
|
460
|
+
case "peity":
|
461
|
+
const type = getPeityType(node);
|
462
|
+
if (type) {
|
463
|
+
peity(node, type);
|
464
|
+
} else {
|
465
|
+
node._peity.unmount();
|
466
|
+
}
|
467
|
+
break;
|
468
|
+
case "data-peity":
|
469
|
+
if (node._peity) {
|
470
|
+
peity(node, node._peity.type);
|
471
|
+
}
|
472
|
+
break;
|
473
|
+
}
|
474
|
+
};
|
475
|
+
|
476
|
+
const callback = (mutationList, observer) => {
|
477
|
+
mutationList.forEach(function (mutation) {
|
478
|
+
switch (mutation.type) {
|
479
|
+
case "childList":
|
480
|
+
for (const node of Array.from(mutation.addedNodes)) {
|
481
|
+
const element = elementFromNode(node);
|
482
|
+
if (element) {
|
483
|
+
processNodeAdded(element);
|
484
|
+
}
|
485
|
+
}
|
486
|
+
for (const node of Array.from(mutation.removedNodes)) {
|
487
|
+
const element = elementFromNode(node);
|
488
|
+
if (element) {
|
489
|
+
processNodeRemoved(element);
|
490
|
+
}
|
491
|
+
}
|
492
|
+
break;
|
493
|
+
case "attributes":
|
494
|
+
processAttributeChanged(mutation);
|
495
|
+
break;
|
496
|
+
}
|
497
|
+
});
|
498
|
+
};
|
499
|
+
|
500
|
+
const observerOptions = {
|
501
|
+
childList: true,
|
502
|
+
attributes: true,
|
503
|
+
subtree: true,
|
504
|
+
};
|
505
|
+
|
506
|
+
const start = async () => {
|
507
|
+
await domReady();
|
508
|
+
|
509
|
+
const observer = new MutationObserver(callback);
|
510
|
+
observer.observe(document.documentElement, observerOptions);
|
511
|
+
|
512
|
+
for (const node of Array.from(document.documentElement.querySelectorAll("[peity]"))) {
|
513
|
+
processNodeAdded(node);
|
514
|
+
}
|
515
|
+
};
|
516
|
+
|
517
|
+
start();
|
518
|
+
|
519
|
+
export { peity as default };
|
@@ -0,0 +1,11 @@
|
|
1
|
+
/*!
|
2
|
+
Peity Vanila Rails 0.2.1
|
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 a=2*t.options.radius;const r=t.prepare(t.options.width||a,t.options.height||a),l=r.clientWidth,h=r.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],a=s/o;let l;if(0!=a){if(1==a)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,a>.5?1:0,1,f(t,d),"L");u?i=i.concat(f(t,u),"A",u,u,0,a>.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)),r.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),a=o.clientWidth,r=o.clientHeight,l=n-s,h=t.options.padding,p=t.fill(),c=t=>t*a/i.length,d=t=>r-(l?(t-s)/l*r:1);for(var u=0;u<i.length;u++){let a,r=c(u+h),m=c(u+1-h)-r,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)):a=1,a=v-y,0==a&&(a=1,n>0&&l&&y--),o.append(e("rect",{"data-value":f,fill:p.call(t,f,u,i),x:r,y:y,width:m,height:a}))}})),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),a=t.options.strokeWidth,r=o.clientWidth,l=o.clientHeight-a,h=n-s,p=t=>{let e=l;return h&&(e-=(t-s)/h*l),e+a/2};let c=p(Math.max(s,0)),d=[0,c];for(var u=0;u<i.length;u++)d.push(u*(r/(i.length-1)),p(i[u]));d.push(r,c),t.options.fill&&o.append(e("polygon",{fill:t.options.fill,points:d.join(" ")})),a&&o.append(e("polyline",{fill:"none",points:d.slice(2,d.length-2).join(" "),stroke:t.options.stroke,"stroke-width":a,"stroke-linecap":"square"}))}));const a=function(t,e,i){const s=new n(t,e,i);return s.mount(),s};a.defaults=n.defaults,a.graphers=n.graphers;const r=t=>t.getAttribute("peity"),l=t=>{if(t.nodeType==Node.ELEMENT_NODE)return t},h=t=>{t.matches("[peity]")&&a(t,r(t))},p=t=>{t._peity&&t._peity.destroy()},c=(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=r(e);t?a(e,t):e._peity.unmount();break;case"data-peity":e._peity&&a(e,e._peity.type)}})(t)}}))},d={childList:!0,attributes:!0,subtree:!0};return(async()=>{await new Promise((t=>{"loading"==document.readyState?document.addEventListener("DOMContentLoaded",t):t()}));new MutationObserver(c).observe(document.documentElement,d);for(const t of Array.from(document.documentElement.querySelectorAll("[peity]")))h(t)})(),a}();
|