1 2 /** 3 * @fileoverview A base chart tooltip. 4 * @version 1.0.0 5 * @see https://google.github.io/styleguide/jsguide.html 6 * @see https://github.com/google/closure-compiler/wiki 7 */ 8 9 10 11 /** 12 * A base chart tooltip. 13 * @constructor 14 */ 15 charts.Tooltip = function() { 16 17 /** 18 * Sets configuration options. 19 * @param {!Object} options The configuration options. 20 * @see charts.BaseChart#getOptions 21 * @example 22 * options: { 23 * 'tooltip': { 24 * 'paddings': '5px', 25 * 'bgcolor': '#fff', 26 * 'opacity': 0.9 27 * } 28 * } 29 */ 30 this.setOptions = function(options) { 31 options_ = options; 32 options_['tooltip'] = options_['tooltip'] || {}; 33 options_['tooltip']['paddings'] = options_['tooltip']['paddings'] || '5px'; 34 options_['tooltip']['bgcolor'] = options_['tooltip']['bgcolor'] || '#fff'; 35 options_['tooltip']['opacity'] = options_['tooltip']['opacity'] || '0.9'; 36 options_['tooltip']['template'] = options_['tooltip']['template'] || 37 '<b>{{ arg.0 }}</b><br>{{ arg.1 }}: {{ arg.2 }}'; 38 }; 39 40 /** 41 * Shows tooltip element. 42 * @param {Event} e The mouse event. 43 * @param {number=} opt_x The optional X coord. 44 * @param {number=} opt_y The optional Y coord. 45 */ 46 this.show = function(e, opt_x, opt_y) { 47 /** @type {!Object.<string, number>} */ var coords = getCoords_(e); 48 /** @type {string} */ var text = getTooltipText_(e); 49 /** @type {number} */ var scrollTop = 50 dom.document.documentElement.scrollTop + dom.document.body.scrollTop; 51 /** @type {number} */ var offsetWidth = 52 window.innerWidth || 53 (dom.document.documentElement || dom.document.body).offsetWidth; 54 55 if (text) { 56 self_.getTooltipElement().innerHTML = text; 57 tooltip_.style.display = 'block'; 58 if (coords.y - scrollTop < tooltip_.offsetHeight) 59 coords.y += tooltip_.offsetHeight; 60 opt_y = opt_y || coords.y - tooltip_.offsetHeight - 5; 61 if (offsetWidth < coords.x + tooltip_.offsetWidth) 62 coords.x -= tooltip_.offsetWidth; 63 opt_x = opt_x || coords.x + 5; 64 tooltip_.style.top = opt_y + 'px'; 65 tooltip_.style.left = opt_x + 'px'; 66 } 67 }; 68 69 /** 70 * Hides tooltip element. 71 * @param {Event} e The mouse event. 72 */ 73 this.hide = function(e) { 74 e = e || window.event || {}; 75 /** @type {Element} */ var target = e.target || e.srcElement; 76 /** @type {Element} */ var related = e.relatedTarget || e.fromElement; 77 if (tooltip_ && tooltip_ != target && tooltip_ != related) 78 tooltip_.style.display = 'none'; 79 }; 80 81 /** 82 * Gets reference to tooltip HTML element. 83 * @return {!Node} Returns reference to tooltip HTML element. 84 */ 85 this.getTooltipElement = function() { 86 if (!tooltip_) { 87 tooltip_ = dom.document.body.appendChild(dom.createElement('DIV')); 88 /** @type {CSSStyleDeclaration} */ var style = tooltip_.style; 89 style.display = 'none'; 90 style.zIndex = 999; 91 style.cursor = 'default'; 92 style.whiteSpace = 'nowrap'; 93 //style.maxWidth = '150px'; 94 style.position = 'absolute'; 95 style.border = 'solid 1px #ccc'; 96 style.fontFamily = options_['font']['family']; 97 style.fontSize = options_['font']['size'] + 'px'; 98 style.padding = options_['tooltip']['paddings']; 99 style.background = options_['tooltip']['bgcolor']; 100 style.borderRadius = '3px'; 101 style.opacity = options_['tooltip']['opacity']; 102 style.filter = 103 'alpha(opacity=' + (options_['tooltip']['opacity'] * 100) + ')'; 104 tooltip_.onmouseout = function() { 105 style.display = 'none'; 106 }; 107 } 108 return tooltip_; 109 }; 110 111 /** 112 * Parses tooltip template content. 113 * @param {...*} var_args 114 * @return {string} Returns parsed tooltip template content. 115 */ 116 this.parse = function(var_args) { 117 /** @type {string} */ var content = options_['tooltip']['template']; 118 /** @type {!Object.<string, *>} */ var params = {}; 119 for (/** @type {number} */ var i = 0; i < arguments.length; i++) { 120 params['arg.' + i] = arguments[i]; 121 } 122 return template_.parse(content, params); 123 }; 124 125 /** 126 * @param {Event} e The mouse event. 127 * @return {!Object.<string, number>} Returns X and Y coordinates. 128 * @private 129 */ 130 function getCoords_(e) { 131 e = e || window.event; 132 /** @type {!Object.<string, number>} */ var result = {x: 0, y: 0}; 133 if (e.pageX || e.pageY) { 134 result = {x: e.pageX, y: e.pageY}; 135 } else if (e.clientX || e.clientY) { 136 /** @type {Element} */ var body = dom.document.body; 137 /** @type {Element} */ var root = dom.document.documentElement; 138 result = { 139 x: e.clientX + (body.scrollLeft || 0) + (root.scrollLeft || 0), 140 y: e.clientY + (body.scrollTop || 0) + (root.scrollTop || 0) 141 }; 142 } 143 return result; 144 } 145 146 /** 147 * @param {Event} e The mouse event. 148 * @return {string} Returns tooltip text. 149 * @private 150 */ 151 function getTooltipText_(e) { 152 e = e || window.event || {}; 153 /** @type {string} */ var text = ''; 154 /** @type {Element} */ var target = e.target || e.srcElement; 155 /** @type {Element} */ var related = e.relatedTarget || e.fromElement || 156 target.previousSibling || target.parentNode; 157 158 try { 159 if ('text' == target.tagName) text = related.getAttribute('tooltip'); 160 else text = target.getAttribute('tooltip'); 161 } catch (ex) {} 162 163 if (!text) { 164 try { 165 text = target.getAttribute('title') || related.getAttribute('tooltip'); 166 target.setAttribute('tooltip', text); 167 target.removeAttribute('title'); 168 } catch (ex) {} 169 } 170 return text; 171 } 172 173 /** 174 * The reference to current class instance. Used in private methods. 175 * @type {!charts.Tooltip} 176 * @private 177 */ 178 var self_ = this; 179 180 /** 181 * Reference to tooltip HTML element. 182 * @type {Node} 183 * @private 184 */ 185 var tooltip_ = null; 186 187 /** 188 * Storage for configuration options. 189 * @dict 190 * @private 191 */ 192 var options_ = null; 193 194 /** 195 * Instance of <code>dom.Template</code>. 196 * @type {!dom.Template} 197 * @see dom.Template 198 * @private 199 */ 200 var template_ = new dom.Template; 201 }; 202