| 1 | #include <string>
 | 
| 2 | 
 | 
| 3 | namespace souffle {
 | 
| 4 | namespace profile {
 | 
| 5 | namespace html {
 | 
| 6 | std::string jsChartistPlugin = R"___(
 | 
| 7 | /**
 | 
| 8 |  * Chartist.js plugin to display a data label on top of the points in a line chart.
 | 
| 9 |  * The MIT License (MIT)
 | 
| 10 |  *
 | 
| 11 |  * Copyright (c) 2015 Markus Padourek
 | 
| 12 |  *
 | 
| 13 |  *  Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
| 14 |  * of this software and associated documentation files (the "Software"), to deal
 | 
| 15 |  * in the Software without restriction, including without limitation the rights
 | 
| 16 |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
| 17 |  * copies of the Software, and to permit persons to whom the Software is
 | 
| 18 |  * furnished to do so, subject to the following conditions:
 | 
| 19 |  *  The above copyright notice and this permission notice shall be included in all
 | 
| 20 |  * copies or substantial portions of the Software.
 | 
| 21 |  *
 | 
| 22 |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
| 23 |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
| 24 |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
| 25 |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
| 26 |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
| 27 |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
| 28 |  * SOFTWARE. **/
 | 
| 29 | 
 | 
| 30 | /* global Chartist */
 | 
| 31 | (function (window, document, Chartist) {
 | 
| 32 |     'use strict';
 | 
| 33 | 
 | 
| 34 |     var defaultOptions = {
 | 
| 35 |         currency: undefined,
 | 
| 36 |         currencyFormatCallback: undefined,
 | 
| 37 |         tooltipOffset: {
 | 
| 38 |             x: 0,
 | 
| 39 |             y: -20
 | 
| 40 |         },
 | 
| 41 |         anchorToPoint: false,
 | 
| 42 |         appendToBody: false,
 | 
| 43 |         class: undefined,
 | 
| 44 |         pointClass: 'ct-point'
 | 
| 45 |     };
 | 
| 46 | 
 | 
| 47 |     Chartist.plugins = Chartist.plugins || {};
 | 
| 48 |     Chartist.plugins.tooltip = function (options) {
 | 
| 49 |         options = Chartist.extend({}, defaultOptions, options);
 | 
| 50 | 
 | 
| 51 |         return function tooltip(chart) {
 | 
| 52 |             var tooltipSelector = options.pointClass;
 | 
| 53 |             if (chart instanceof Chartist.Bar) {
 | 
| 54 |                 tooltipSelector = 'ct-bar';
 | 
| 55 |             } else if (chart instanceof Chartist.Pie) {
 | 
| 56 |                 // Added support for donut graph
 | 
| 57 |                 if (chart.options.donut) {
 | 
| 58 |                     tooltipSelector = 'ct-slice-donut';
 | 
| 59 |                 } else {
 | 
| 60 |                     tooltipSelector = 'ct-slice-pie';
 | 
| 61 |                 }
 | 
| 62 |             }
 | 
| 63 | 
 | 
| 64 |             var $chart = chart.container;
 | 
| 65 |             var $toolTip = $chart.querySelector('.chartist-tooltip');
 | 
| 66 |             if (!$toolTip) {
 | 
| 67 |                 $toolTip = document.createElement('div');
 | 
| 68 |                 $toolTip.className = (!options.class) ? 'chartist-tooltip' : 'chartist-tooltip ' + options.class;
 | 
| 69 |                 if (!options.appendToBody) {
 | 
| 70 |                     $chart.appendChild($toolTip);
 | 
| 71 |                 } else {
 | 
| 72 |                     document.body.appendChild($toolTip);
 | 
| 73 |                 }
 | 
| 74 |             }
 | 
| 75 |             var height = $toolTip.offsetHeight;
 | 
| 76 |             var width = $toolTip.offsetWidth;
 | 
| 77 | 
 | 
| 78 |             hide($toolTip);
 | 
| 79 | 
 | 
| 80 |             function on(event, selector, callback) {
 | 
| 81 |                 $chart.addEventListener(event, function (e) {
 | 
| 82 |                     if (!selector || hasClass(e.target, selector))
 | 
| 83 |                         callback(e);
 | 
| 84 |                 });
 | 
| 85 |             }
 | 
| 86 | 
 | 
| 87 |             on('mouseover', tooltipSelector, function (event) {
 | 
| 88 |                 var $point = event.target;
 | 
| 89 |                 var tooltipText = '';
 | 
| 90 | 
 | 
| 91 |                 var isPieChart = (chart instanceof Chartist.Pie) ? $point : $point.parentNode;
 | 
| 92 |                 var seriesName = (isPieChart) ? $point.parentNode.getAttribute('ct:meta') || $point.parentNode.getAttribute('ct:series-name') : '';
 | 
| 93 |                 var meta = $point.getAttribute('ct:meta') || seriesName || '';
 | 
| 94 |                 var hasMeta = !!meta;
 | 
| 95 |                 var value = $point.getAttribute('ct:value');
 | 
| 96 |                 if (options.transformTooltipTextFnc && typeof options.transformTooltipTextFnc === 'function') {
 | 
| 97 |                     value = options.transformTooltipTextFnc(value);
 | 
| 98 |                 }
 | 
| 99 | 
 | 
| 100 |                 if (options.tooltipFnc && typeof options.tooltipFnc === 'function') {
 | 
| 101 |                     tooltipText = options.tooltipFnc(meta, value);
 | 
| 102 |                 } else {
 | 
| 103 |                     if (options.metaIsHTML) {
 | 
| 104 |                         var txt = document.createElement('textarea');
 | 
| 105 |                         txt.innerHTML = meta;
 | 
| 106 |                         meta = txt.value;
 | 
| 107 |                     }
 | 
| 108 | 
 | 
| 109 |                     meta = '<span class="chartist-tooltip-meta">' + meta + '</span>';
 | 
| 110 | 
 | 
| 111 |                     if (hasMeta) {
 | 
| 112 |                         tooltipText += meta + '<br>';
 | 
| 113 |                     } else {
 | 
| 114 |                         // For Pie Charts also take the labels into account
 | 
| 115 |                         // Could add support for more charts here as well!
 | 
| 116 |                         if (chart instanceof Chartist.Pie) {
 | 
| 117 |                             var label = next($point, 'ct-label');
 | 
| 118 |                             if (label) {
 | 
| 119 |                                 tooltipText += text(label) + '<br>';
 | 
| 120 |                             }
 | 
| 121 |                         }
 | 
| 122 |                     }
 | 
| 123 | 
 | 
| 124 |                     if (value) {
 | 
| 125 |                         if (value % 1 === 0) {
 | 
| 126 |                             value = '<span class="chartist-tooltip-value">' + minify_numbers(value) + '</span>';
 | 
| 127 |                             tooltipText += value;
 | 
| 128 |                         } else {
 | 
| 129 |                             value = '<span class="chartist-tooltip-value">' + humanise_time(parseFloat(value)) + '</span>';
 | 
| 130 |                             tooltipText += value;
 | 
| 131 |                         }
 | 
| 132 |                     }
 | 
| 133 |                 }
 | 
| 134 | 
 | 
| 135 |                 if(tooltipText) {
 | 
| 136 |                     $toolTip.innerHTML = tooltipText;
 | 
| 137 |                     setPosition(event);
 | 
| 138 |                     show($toolTip);
 | 
| 139 | 
 | 
| 140 |                     // Remember height and width to avoid wrong position in IE
 | 
| 141 |                     height = $toolTip.offsetHeight;
 | 
| 142 |                     width = $toolTip.offsetWidth;
 | 
| 143 |                 }
 | 
| 144 |             });
 | 
| 145 | 
 | 
| 146 |             on('mouseout', tooltipSelector, function () {
 | 
| 147 |                 hide($toolTip);
 | 
| 148 |             });
 | 
| 149 | 
 | 
| 150 |             on('mousemove', null, function (event) {
 | 
| 151 |                 if (false === options.anchorToPoint)
 | 
| 152 |                     setPosition(event);
 | 
| 153 |             });
 | 
| 154 | 
 | 
| 155 |             function setPosition(event) {
 | 
| 156 |                 height = height || $toolTip.offsetHeight;
 | 
| 157 |                 width = width || $toolTip.offsetWidth;
 | 
| 158 |                 var offsetX = - width / 2 + options.tooltipOffset.x;
 | 
| 159 |                 var offsetY = - height + options.tooltipOffset.y;
 | 
| 160 |                 var anchorX, anchorY;
 | 
| 161 | 
 | 
| 162 |                 if (!options.appendToBody) {
 | 
| 163 |                     var scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
 | 
| 164 |                     var top = event.pageY - window.pageYOffset + scrollTop ;
 | 
| 165 |                     var left = event.pageX- window.pageXOffset;
 | 
| 166 | 
 | 
| 167 |                     if (true === options.anchorToPoint && event.target.x2 && event.target.y2) {
 | 
| 168 |                         anchorX = parseInt(event.target.x2.baseVal.value);
 | 
| 169 |                         anchorY = parseInt(event.target.y2.baseVal.value);
 | 
| 170 |                     }
 | 
| 171 | 
 | 
| 172 |                     $toolTip.style.top = (anchorY || top) + offsetY + 'px';
 | 
| 173 |                     $toolTip.style.left = (anchorX || left) + offsetX + 'px';
 | 
| 174 |                 } else {
 | 
| 175 |                     $toolTip.style.top = event.pageY + offsetY + 'px';
 | 
| 176 |                     $toolTip.style.left = event.pageX + offsetX + 'px';
 | 
| 177 |                 }
 | 
| 178 |             }
 | 
| 179 |         }
 | 
| 180 |     };
 | 
| 181 | 
 | 
| 182 |     function show(element) {
 | 
| 183 |         if(!hasClass(element, 'tooltip-show')) {
 | 
| 184 |             element.className = element.className + ' tooltip-show';
 | 
| 185 |         }
 | 
| 186 |     }
 | 
| 187 | 
 | 
| 188 |     function hide(element) {
 | 
| 189 |         var regex = new RegExp('tooltip-show' + '\\s*', 'gi');
 | 
| 190 |         element.className = element.className.replace(regex, '').trim();
 | 
| 191 |     }
 | 
| 192 | 
 | 
| 193 |     function hasClass(element, className) {
 | 
| 194 |         return (' ' + element.getAttribute('class') + ' ').indexOf(' ' + className + ' ') > -1;
 | 
| 195 |     }
 | 
| 196 | 
 | 
| 197 |     function next(element, className) {
 | 
| 198 |         do {
 | 
| 199 |             element = element.nextSibling;
 | 
| 200 |         } while (element && !hasClass(element, className));
 | 
| 201 |         return element;
 | 
| 202 |     }
 | 
| 203 | 
 | 
| 204 |     function text(element) {
 | 
| 205 |         return element.innerText || element.textContent;
 | 
| 206 |     }
 | 
| 207 | 
 | 
| 208 | } (window, document, Chartist));
 | 
| 209 | 
 | 
| 210 | )___";
 | 
| 211 | }
 | 
| 212 | }  // namespace profile
 | 
| 213 | }  // namespace souffle
 |