// Of course, you can never fully protect against people deliberately wanting to spam.
var get_unique = function() {
var use_local_storage = supports_html5_storage();
- if (use_local_storage && localStorage['unique']) {
- return localStorage['unique'];
+ if (use_local_storage && window['localStorage']['unique']) {
+ return window['localStorage']['unique'];
}
var unique = Math.random();
if (use_local_storage) {
- localStorage['unique'] = unique;
+ window['localStorage']['unique'] = unique;
}
return unique;
}
var arrow_size = arrow.arrow_size * zoom_factor;
var square_width = document.querySelector(".square-a8").getBoundingClientRect().width;
- var pos, from_y, to_y, from_x, to_x;
+ var from_y, to_y, from_x, to_x;
if (board.orientation() === 'black') {
- pos = document.querySelector(".square-h1").getBoundingClientRect(); // FIXME: margin?
from_y = (arrow.from_row + 0.5)*square_width;
to_y = (arrow.to_row + 0.5)*square_width;
from_x = (7 - arrow.from_col + 0.5)*square_width;
to_x = (7 - arrow.to_col + 0.5)*square_width;
} else {
- pos = document.querySelector(".square-a8").getBoundingClientRect(); // FIXME: margin?
from_y = (7 - arrow.from_row + 0.5)*square_width;
to_y = (7 - arrow.to_row + 0.5)*square_width;
from_x = (arrow.from_col + 0.5)*square_width;
head.setAttribute("fill", arrow.fg_color);
svg.appendChild(head);
- svg.style.top = pos.top;
- svg.style.left = pos.left;
+ svg.style.top = '2px'; /* Border for .board-b72b1. */
+ svg.style.left = '2px';
svg.style.pointerEvents = 'none';
- document.body.appendChild(svg);
+ document.getElementById('board').appendChild(svg);
arrow.svg = svg;
}
} else if (truncate_display_history) {
document.getElementById("history").innerHTML = print_pv(0, null, 8, true);
} else {
- document.getElementById("history").html(
+ document.getElementById("history").innerHTML =
'(<a class="move" href="javascript:collapse_history(true)">collapse</a>) ' +
- print_pv(0, null));
+ print_pv(0, null);
}
}
}
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']) {
}
// 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) {
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
*/
document.getElementById("soundoff").innerHTML = "<strong>Off</strong>";
}
if (supports_html5_storage()) {
- localStorage['enable_sound'] = enable_sound ? 1 : 0;
+ window['localStorage']['enable_sound'] = enable_sound ? 1 : 0;
}
}
window['set_sound'] = set_sound;
unique = get_unique();
// Load settings from HTML5 local storage if available.
- if (supports_html5_storage() && localStorage['enable_sound']) {
- set_sound(parseInt(localStorage['enable_sound']));
+ if (supports_html5_storage() && window['localStorage']['enable_sound']) {
+ set_sound(parseInt(window['localStorage']['enable_sound']));
} else {
set_sound(false);
}