Graph tweaks

Determine the correct height of the bar from the data-value and the given height of the tbody rather than including an explicit data-height on the bar.

Better algorithm to determine where to draw horizontal lines on the graph.

Only display the top 10 geolocated search locations with the rest falling under "Other", unless there are only 11 locations in the list.
This commit is contained in:
Brian Huisman 2023-11-06 11:27:15 -05:00
parent 9e5dccf8b7
commit 0c1f359ef0
2 changed files with 66 additions and 40 deletions

View file

@ -2706,19 +2706,37 @@ ORCINUS;
</tr>
</thead>
<tbody><?php
foreach ($locCount as $iso => $searches) { ?>
<tr>
<th scope="row"><?php
if (file_exists(__DIR__.'/img/flags/'.strtolower($iso).'.png')) { ?>
<img src="img/flags/<?php echo strtolower($iso); ?>.png" alt="<?php echo strtoupper($iso); ?>" title="<?php echo $locData[$iso]; ?>" class="svg-icon-flag"><?php
} else { ?>
<img src="img/help.svg" alt="?" title="<?php echo $locData[$iso]; ?>" class="svg-icon"><?php
} ?>
<span class="align-middle"><?php echo $locData[$iso]; ?></span>
</th>
<td class="text-end"><?php echo $searches; ?></td>
<td class="text-center"><small>(<?php echo round($searches / array_sum($locCount) * 100, 1); ?>%)</small></td>
</tr><?php
$top10 = 0;
foreach ($locCount as $iso => $searches) {
if ($top10++ < 10 || $iso == array_key_last($locCount)) { ?>
<tr>
<th scope="row"><?php
if (file_exists(__DIR__.'/img/flags/'.strtolower($iso).'.png')) { ?>
<img src="img/flags/<?php echo strtolower($iso); ?>.png" alt="<?php echo strtoupper($iso); ?>" title="<?php echo $locData[$iso]; ?>" class="svg-icon-flag"><?php
} else { ?>
<img src="img/help.svg" alt="?" title="<?php echo $locData[$iso]; ?>" class="svg-icon"><?php
} ?>
<span class="align-middle"><?php echo $locData[$iso]; ?></span>
</th>
<td class="text-end"><?php echo $searches; ?></td>
<td class="text-center"><small>(<?php echo round($searches / array_sum($locCount) * 100, 1); ?>%)</small></td>
</tr><?php
} else {
$cap = false; $hits = 0;
foreach ($locCount as $iso2 => $searches2) {
if ($iso2 == $iso) $capture = true;
if ($capture) $hits += $searches2;
} ?>
<tr>
<th scope="row">
<img src="img/help.svg" alt="?" title="Other" class="svg-icon">
<span class="align-middle">Other</span>
</th>
<td class="text-end"><?php echo $hits; ?></td>
<td class="text-center"><small>(<?php echo round($hits / array_sum($locCount) * 100, 1); ?>%)</small></td>
</tr><?php
break;
}
} ?>
</tbody>
</table>
@ -2740,17 +2758,15 @@ ORCINUS;
<li class="list-group-item">
<h4>All Searches by Day of Week</h4>
<table class="bar-graph d-flex align-items-end position-relative w-100 gap-1 pt-4 mb-5">
<tbody class="flex-fill d-flex gap-3"><?php
<tbody class="flex-fill d-flex gap-3" style="height:14em;"><?php
foreach ($dayWalker as $day => $value) { ?>
<tr class="flex-fill d-flex flex-column justify-content-end<?php
if ($day == 'Sun') echo ' ps-2';
if ($day == 'Sat') echo ' pe-2'; ?>">
if ($day == array_key_first($dayWalker)) echo ' ps-2';
if ($day == array_key_last($dayWalker)) echo ' pe-2'; ?>">
<th class="position-relative p-0">
<span class="position-absolute top-0 start-50 translate-middle-x"><?php echo $day; ?></span>
</th>
<td class="order-first position-relative bg-secondary bg-gradient p-0" data-height="<?php
echo round($value / (max($dayWalker) / 200));
?>" data-value="<?php echo $value; ?>" title="<?php echo $day; ?>">
<td class="order-first position-relative bg-secondary bg-gradient p-0" data-value="<?php echo $value; ?>" title="<?php echo $day; ?>">
<small class="position-absolute bottom-100 start-50 translate-middle-x"><?php echo $value; ?></small>
</td>
</tr><?php
@ -2761,17 +2777,15 @@ ORCINUS;
<li class="list-group-item">
<h4>All Searches by Time of Day</h4>
<table class="bar-graph d-flex align-items-end position-relative w-100 gap-1 pt-4 mb-5">
<tbody class="flex-fill d-flex gap-1"><?php
<tbody class="flex-fill d-flex gap-1" style="height:14em;"><?php
foreach ($hourWalker as $hour => $value) { ?>
<tr class="flex-fill d-flex flex-column justify-content-end<?php
if ($hour == '00:00') echo ' ps-2';
if ($hour == '23:00') echo ' pe-2'; ?>">
if ($hour == array_key_first($hourWalker)) echo ' ps-2';
if ($hour == array_key_last($hourWalker)) echo ' pe-2'; ?>">
<th class="position-relative p-0">
<time class="position-absolute top-0 start-50 translate-middle-x"><?php echo $hour; ?></time>
</th>
<td class="order-first position-relative bg-secondary bg-gradient p-0" data-height="<?php
echo (max($hourWalker)) ? round($value / (max($hourWalker) / 200)) : 0;
?>" data-value="<?php echo $value; ?>" title="<?php echo $hour; ?>">
<td class="order-first position-relative bg-secondary bg-gradient p-0" data-value="<?php echo $value; ?>" title="<?php echo $hour; ?>">
<small class="position-absolute bottom-100 start-50 translate-middle-x"><?php echo $value; ?></small>
</td>
</tr><?php

View file

@ -359,22 +359,25 @@ for (let x = 0; x < os_index_with_selected.length; x++) {
/* ***** Page >> Search Statistics ********************************* */
let bars = document.querySelectorAll('table.bar-graph td[data-height]');
let bars = document.querySelectorAll('table.bar-graph td[data-value]');
for (let x = 0; x < bars.length; x++) {
bars[x].style.height = '0px';
bars[x].style.transition = 'height 0.8s ease';
let tb = bars[x].parentNode.parentNode;
if (tb.offsetHeight <= parseInt(bars[x].getAttribute('data-height'))) {
tb.style.height = bars[x].getAttribute('data-height') + 'px';
tb.dataMaxValue = bars[x].getAttribute('data-value');
}
setTimeout((function(elem) {
elem.style.height = elem.getAttribute('data-height') + 'px';
})(bars[x]), 5);
bars[x].tbody = bars[x].parentNode.parentNode;
if (!bars[x].tbody.dataMaxValue) bars[x].tbody.dataMaxValue = 0;
bars[x].tbody.dataMaxValue = Math.max(
parseFloat(bars[x].getAttribute('data-value')),
bars[x].tbody.dataMaxValue
);
setTimeout((function(elem) { return function() {
elem.style.height = (parseFloat(elem.getAttribute('data-value') / elem.tbody.dataMaxValue) * elem.tbody.offsetHeight) + 'px';
}})(bars[x]), 5);
}
let graphs = document.querySelectorAll('table.bar-graph');
let ticks = [1, 5, 10, 50, 100, 500, 1000, 5000, 10000, 50000, 100000, 500000, 1000000];
for (let x = 0; x < graphs.length; x++) {
let thead = graphs[x].getElementsByTagName('thead');
if (!thead.length) {
@ -383,13 +386,23 @@ for (let x = 0; x < graphs.length; x++) {
// Adjust background lines
if (tbody.dataMaxValue) {
graphs[x].unitHeight = tbody.offsetHeight / tbody.dataMaxValue;
} else graphs[x].unitHeight = tbody.offsetHeight;
// 5 intervals by default?
graphs[x].interval = tbody.offsetHeight / 5;
let divisions = 1;
do {
graphs[x].interval = tbody.dataMaxValue / divisions;
} while (
graphs[x].interval * graphs[x].unitHeight > 20 &&
divisions < tbody.dataMaxValue &&
divisions++ < tbody.offsetHeight / 50
);
graphs[x].interval = Math.max(1, Math.round(graphs[x].interval / graphs[x].unitHeight / 5) * 5 * graphs[x].unitHeight, graphs[x].unitHeight);
let divVal = Math.floor(Math.log10(tbody.dataMaxValue));
graphs[x].interval = Math.max(1, Math.round(graphs[x].interval / ticks[divVal])) * ticks[divVal] * graphs[x].unitHeight;
} else {
graphs[x].unitHeight = tbody.offsetHeight;
graphs[x].interval = tbody.offsetHeight;
}
thead = document.createElement('thead');
let tr = document.createElement('tr');
@ -397,8 +410,7 @@ for (let x = 0; x < graphs.length; x++) {
for (let y = 0; y < Math.ceil(tbody.offsetHeight / graphs[x].interval); y++) {
let td = document.createElement('td');
td.classList.add('d-flex', 'flex-column', 'justify-content-end', 'text-end');
td.style.height = graphs[x].interval + 'px';
td.style.transform = 'translatey(0.6em)';
td.style.height = Math.min(tbody.offsetHeight, graphs[x].interval) + 'px';
let small = document.createElement('small');
small.appendChild(document.createTextNode(Math.round(y * graphs[x].interval / graphs[x].unitHeight)));
td.appendChild(small);