]> git.sesse.net Git - remoteglot/commitdiff
Make our own SVG sparkline, replacing jquery.sparkline.js.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Fri, 23 Dec 2022 16:12:50 +0000 (17:12 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Fri, 23 Dec 2022 16:12:50 +0000 (17:12 +0100)
build.sh
www/css/remoteglot.css
www/index.dev.html
www/js/remoteglot.js

index 848714a417241a33e01d9248e212079ce04d6ed6..c970b1330c1c1c360b670ed31c9908b6fdf6a85e 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -3,22 +3,15 @@
 # Download http://dl.google.com/closure-compiler/compiler-latest.zip
 # and unzip it in closure/ before running this script.
 
-# The JQuery build comes from http://projects.jga.me/jquery-builder/,
-# more specifically
-#
-# https://raw.githubusercontent.com/jgallen23/jquery-builder/0.7.0/dist/2.1.1/jquery-deprecated-sizzle.js
-
 umask 022
 
 java -jar closure-compiler-v20221004.jar \
        --language_in ECMASCRIPT_2018 \
        --compilation_level SIMPLE \
        --js_output_file=www/js/remoteglot.min.js \
-        www/js/jquery-deprecated-sizzle.js \
        www/js/chessboard-0.3.0.js \
        www/js/chess.js \
        www/js/json_delta.js \
-       www/js/jquery.sparkline.js \
        www/js/remoteglot.js
 
 cat www/css/chessboard-0.3.0.css www/css/remoteglot.css | sass --scss -t compressed > www/css/remoteglot.min.css
index a928985e8b2abc19fbeb22f480e3a3ba3bfdc9d4..c2aba8fd410f885aaa861135b42e74ab726f2152 100644 (file)
@@ -14,17 +14,35 @@ h3 {
 #scorecontainer {
        font-size: x-large;
        margin-top: 0;
+       display: grid;
+       grid-template-columns: max-content 1fr;
+       gap: 12px;
 }
 #score {
-       float: left;
+       grid-column: 1;
 }
 #scoresparkcontainer {
+       grid-column: 2;
        overflow: hidden;
+       height: 0.85em;
+       margin-top: 0.15em;
+       width: 100%;
 }
 #scorespark {
        margin-left: 0.5em;
        margin-right: 0.5em;
 }
+#sparklinehover {
+       position: absolute;
+       display: none;
+       background-color: rgba(0, 0, 0, 0.6);
+       color: white;
+       font-size: 10px;
+       white-space: nowrap;
+       padding: 5px;
+       border: 1px solid white;
+       z-index: 10000;
+}
 #pvcontainer {
        clear: left;
        margin-top: 1em;
index 139075eb7d5802986b5be05a18bb2619cce0a7d4..e04ef3ab1db6d9c6b75490ffc4fe534c56e705ce 100644 (file)
   <!-- end replace -->
 
   <!-- replace <script>[js/remoteglot.min.js]</script> -->
-  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
   <script type="text/javascript" src="js/chessboard-0.3.0.js"></script>
   <script type="text/javascript" src="js/chess.js"></script>
   <script type="text/javascript" src="js/json_delta.js"></script>
-  <script type="text/javascript" src="js/jquery.sparkline.js"></script>
   <script type="text/javascript" src="js/remoteglot.js"></script>
   <!-- end replace -->
 </head>
@@ -39,9 +37,9 @@
 <div id="analysis">
   <div id="scorecontainer">
     <span id="score">Score:</span>
-    <div id="scoresparkcontainer">
-      <span id="scorespark"></span>
-    </div>
+    <svg xmlns="http://www.w3.org/2000/svg" id="scoresparkcontainer">
+    </svg>
+    <div id="sparklinehover"></div>
   </div>
   <p id="pvcontainer"><strong id="pvtitle">PV:</strong> <span id="pv"></span></p>
   <p id="searchstats"></p>
index 61c390f32db4e2573e04ecb4237bfdb2f47a3722..beaf63f74f1bfcba4437c3e4a6ca94aa30a91736 100644 (file)
@@ -1361,6 +1361,8 @@ var update_board = function() {
 }
 
 var update_sparkline = function(data) {
+       let scorespark = document.getElementById('scoresparkcontainer');
+       scorespark.textContent = '';
        if (data && data['score_history']) {
                var first_move_num = undefined;
                for (var halfmove_num in data['score_history']) {
@@ -1376,17 +1378,13 @@ var update_sparkline = function(data) {
                        }
 
                        // Possibly truncate some moves if we don't have enough width.
-                       // FIXME: Sometimes width() for #scorecontainer (and by extent,
-                       // #scoresparkcontainer) on Chrome for mobile seems to start off
-                       // at something very small, and then suddenly snap back into place.
-                       // Figure out why.
-                       var max_moves = Math.floor(document.getElementById("scoresparkcontainer").getBoundingClientRect().width / 5) - 5;
+                       var max_moves = Math.floor(scorespark.getBoundingClientRect().width / 5) - 3;
                        if (last_move_num - first_move_num > max_moves) {
                                first_move_num = last_move_num - max_moves;
                        }
 
-                       var min_score = -100;
-                       var max_score = 100;
+                       var min_score = -1;
+                       var max_score = 1;
                        var last_score = null;
                        var scores = [];
                        for (var halfmove_num = first_move_num; halfmove_num <= last_move_num; ++halfmove_num) {
@@ -1401,36 +1399,77 @@ var update_sparkline = function(data) {
                        if (data['score']) {
                                scores.push(compute_plot_score(data['score']));
                        }
-                       // FIXME: at some widths, calling sparkline() seems to push
-                       // #scorecontainer under the board.
-                       $('#scorespark').unbind('sparklineClick');
-                       $('#scorespark').sparkline(scores, {
-                               type: 'bar',
-                               zeroColor: 'gray',
-                               chartRangeMin: min_score,
-                               chartRangeMax: max_score,
-                               tooltipFormatter: function(sparkline, options, fields) {
-                                       // score_history contains the Nth _position_, but format_tooltip
-                                       // wants to format the Nth _move_; thus the -1.
-                                       return format_tooltip(data, fields[0].offset + first_move_num - 1);
+
+                       const h = scorespark.getBoundingClientRect().height;
+
+                       let base_y = h - h * min_score / (min_score - max_score);
+                       for (let i = 0; i < scores.length; ++i) {
+                               let rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
+                               //rect.setAttributeNS(null, 'stroke', "#000000");
+                               rect.setAttributeNS(null, 'x', i * 5)
+                               rect.setAttributeNS(null, 'width', 4);
+                               let extent = scores[i] * h / (max_score - min_score);
+                               if (extent > 0 && extent < 1) {
+                                       extent = 1;
+                               } else if (extent < 0 && extent > -1) {
+                                       extent = -1;
                                }
-                       });
-                       $('#scorespark').unbind('sparklineClick');
-                       $('#scorespark').bind('sparklineClick', function(event) {
-                               var sparkline = event.sparklines[0];
-                               var region = sparkline.getCurrentRegionFields();
-                               if (region[0].offset !== undefined) {
-                                       show_line(0, first_move_num + region[0].offset - 1);
+
+                               let color;
+                               if (scores[i] === 0) {
+                                       color = [0.5, 0.5, 0.5];
+                                       rect.setAttributeNS(null, 'y', base_y - 1);
+                                       rect.setAttributeNS(null, 'height', 1);
+                               } else if (scores[i] > 0) {
+                                       color = [0.2, 0.4, 0.8];
+                                       rect.setAttributeNS(null, 'y', base_y - extent);
+                                       rect.setAttributeNS(null, 'height', extent);
+                               } else {
+                                       color = [1.0, 0.267, 0.267];
+                                       rect.setAttributeNS(null, 'y', base_y);
+                                       rect.setAttributeNS(null, 'height', -extent);
                                }
-                       });
-               } else {
-                       document.getElementById("scorespark").textContent = "";
+                               let hlcolor = [color[0], color[1], color[2]];
+                               if (scores[i] !== 0) { 
+                                       hlcolor[0] = Math.min(hlcolor[0] * 1.4, 1.0);
+                                       hlcolor[1] = Math.min(hlcolor[1] * 1.4, 1.0);
+                                       hlcolor[2] = Math.min(hlcolor[2] * 1.4, 1.0);
+                               }
+                               rect.style.fill = 'rgb(' + color[0]*100.0 + '%, ' + color[1]*100.0 + '%, ' + color[2]*100.0 + '%)';
+
+                               // score_history contains the Nth _position_, but format_tooltip
+                               // wants to format the Nth _move_; thus the -1.
+                               const tooltip = format_tooltip(data, i + first_move_num - 1);
+                               rect.addEventListener('mouseenter', (e) => draw_hover(e, hlcolor, tooltip));
+                               rect.addEventListener('mousemove', (e) => draw_hover(e, hlcolor, tooltip));
+                               rect.addEventListener('mouseleave', (e) => hide_hover(e, color));
+                               rect.addEventListener('click', (e) => show_line(0, i + first_move_num - 1));
+                               scorespark.appendChild(rect);
+                       }
                }
-       } else {
-               document.getElementById("scorespark").textContent = "";
        }
 }
 
+var draw_hover = function(e, color, tooltip) {
+       e.target.style.fill = 'rgb(' + color[0]*100.0 + '%, ' + color[1]*100.0 + '%, ' + color[2]*100.0 + '%)';
+
+       let hover = document.getElementById('sparklinehover');
+       hover.textContent = tooltip;
+       hover.style.display = 'initial';
+
+       let left = Math.max(e.pageX + 10, window.pageXOffset);
+       let top = Math.max(e.pageY - hover.getBoundingClientRect().height, window.pageYOffset);
+       left = Math.min(left, window.pageXOffset + document.documentElement.clientWidth - hover.getBoundingClientRect().width);
+
+       hover.style.left = left + 'px';
+       hover.style.top = top + 'px';
+
+}
+var hide_hover = function(e, color) {
+       e.target.style.fill = 'rgb(' + color[0]*100.0 + '%, ' + color[1]*100.0 + '%, ' + color[2]*100.0 + '%)';
+       document.getElementById('sparklinehover').style.display = 'none';
+}
+
 /**
  * @param {number} num_viewers
  */