+ return element;
+}
+
+function add_th(tr, text, colspan) {
+ let element = add_cell(tr, 'th', text);
+ if (colspan > 0) {
+ element.setAttribute('colspan', colspan);
+ } else {
+ element.setAttribute('colspan', '3');
+ }
+ return element;
+}
+
+function add_3cell(tr, text, cls) {
+ let p1 = add_cell(tr, 'td', '');
+ let element = add_cell(tr, 'td', text);
+ let p2 = add_cell(tr, 'td', '');
+
+ p1.classList.add('pad');
+ p2.classList.add('pad');
+ if (cls === undefined) {
+ element.classList.add('num');
+ } else {
+ element.classList.add(cls);
+ }
+ return element;
+}
+
+function add_3cell_with_filler_ci(tr, text, cls) {
+ let element = add_3cell(tr, text, cls);
+
+ let svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
+ svg.classList.add('fillerci');
+ svg.setAttribute('width', ci_width);
+ svg.setAttribute('height', ci_height);
+ element.appendChild(svg);
+
+ return element;
+}
+
+function add_3cell_ci(tr, ci) {
+ if (isNaN(ci.val)) {
+ add_3cell_with_filler_ci(tr, 'N/A');
+ return;
+ }
+
+ let text;
+ if (ci.format === 'percentage') {
+ text = (100 * ci.val).toFixed(0) + '%';
+ } else {
+ text = ci.val.toFixed(2);
+ }
+ let element = add_3cell(tr, text);
+ let to_x = (val) => { return ci_width * (val - ci.min) / (ci.max - ci.min); };
+
+ // Container.
+ let svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
+ if (ci.inverted === true) {
+ svg.classList.add('invertedci');
+ } else {
+ svg.classList.add('ci');
+ }
+ svg.setAttribute('width', ci_width);
+ svg.setAttribute('height', ci_height);
+
+ // The good (green) and red (bad) ranges.
+ let s0 = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
+ s0.classList.add('range');
+ s0.classList.add('s0');
+ s0.setAttribute('width', to_x(ci.desired));
+ s0.setAttribute('height', ci_height);
+ s0.setAttribute('x', '0');
+
+ let s1 = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
+ s1.classList.add('range');
+ s1.classList.add('s1');
+ s1.setAttribute('width', ci_width - to_x(ci.desired));
+ s1.setAttribute('height', ci_height);
+ s1.setAttribute('x', to_x(ci.desired));
+
+ // Confidence bar.
+ let bar = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
+ bar.classList.add('bar');
+ bar.setAttribute('width', to_x(ci.upper_ci) - to_x(ci.lower_ci));
+ bar.setAttribute('height', ci_height / 3);
+ bar.setAttribute('x', to_x(ci.lower_ci));
+ bar.setAttribute('y', ci_height / 3);
+
+ // Marker line for average.
+ let marker = document.createElementNS('http://www.w3.org/2000/svg', 'line');
+ marker.classList.add('marker');
+ marker.setAttribute('x1', to_x(ci.val));
+ marker.setAttribute('x2', to_x(ci.val));
+ marker.setAttribute('y1', ci_height / 6);
+ marker.setAttribute('y2', ci_height * 5 / 6);
+
+ svg.appendChild(s0);
+ svg.appendChild(s1);
+ svg.appendChild(bar);
+ svg.appendChild(marker);
+
+ element.appendChild(svg);