// version: 2014-08-16 /** * o--------------------------------------------------------------------------------o * | This file is part of the RGraph package - you can learn more at: | * | | * | http://www.rgraph.net | * | | * | This package is licensed under the Creative Commons BY-NC license. That means | * | that for non-commercial purposes it's free to use and for business use there's | * | a 99 GBP per-company fee to pay. You can read the full license here: | * | | * | http://www.rgraph.net/license | * o--------------------------------------------------------------------------------o */ RGraph = window.RGraph || {isRGraph: true}; // Module pattern (function (win, doc, undefined) { var RG = RGraph, ua = navigator.userAgent, ma = Math; /** * This is used in two functions, hence it's here */ RG.tooltips = {}; RG.tooltips.padding = '3px'; RG.tooltips.font_face = 'Tahoma'; RG.tooltips.font_size = '10pt'; /** * Shows a tooltip next to the mouse pointer * * @param canvas object The canvas element object * @param text string The tooltip text * @param int x The X position that the tooltip should appear at. Combined with the canvases offsetLeft * gives the absolute X position * @param int y The Y position the tooltip should appear at. Combined with the canvases offsetTop * gives the absolute Y position * @param int idx The index of the tooltip in the graph objects tooltip array * @param object e The event object */ RG.tooltip = RG.Tooltip = function (obj, text, x, y, idx, e) { /** * chart.tooltip.override allows you to totally take control of rendering the tooltip yourself */ if (typeof(obj.Get('chart.tooltips.override')) == 'function') { return obj.Get('chart.tooltips.override')(obj, text, x, y, idx); } /** * Save the X/Y coords */ var originalX = x; var originalY = y; /** * This facilitates the "id:xxx" format */ text = RGraph.getTooltipTextFromDIV(text); /** * First clear any exising timers */ var timers = RGraph.Registry.Get('chart.tooltip.timers'); if (timers && timers.length) { for (i=0; i 0) { tooltipObj.style.border = '1px #bbb solid'; } tooltipObj.style.borderRadius = '5px'; tooltipObj.style.MozBorderRadius = '5px'; tooltipObj.style.WebkitBorderRadius = '5px'; tooltipObj.style.WebkitBoxShadow = 'rgba(96,96,96,0.5) 0 0 15px'; tooltipObj.style.MozBoxShadow = 'rgba(96,96,96,0.5) 0 0 15px'; tooltipObj.style.boxShadow = 'rgba(96,96,96,0.5) 0 0 15px'; tooltipObj.style.filter = 'progid:DXImageTransform.Microsoft.Shadow(color=#666666,direction=135)'; tooltipObj.style.opacity = 0; //tooltipObj.style.overflow = 'hidden'; tooltipObj.innerHTML = text; tooltipObj.__text__ = text; // This is set because the innerHTML can change when it's set tooltipObj.__canvas__ = obj.canvas; tooltipObj.style.display = 'inline'; tooltipObj.id = '__rgraph_tooltip_' + obj.canvas.id + '_' + obj.uid + '_'+ idx; tooltipObj.__event__ = obj.Get('chart.tooltips.event') || 'click'; tooltipObj.__object__ = obj; if (typeof(idx) == 'number') { tooltipObj.__index__ = idx; origIdx = idx; } if (obj.type == 'line' || obj.type == 'radar') { for (var ds=0; ds= obj.data[ds].length) { idx -= obj.data[ds].length; } else { break; } } tooltipObj.__dataset__ = ds; tooltipObj.__index2__ = idx; } document.body.appendChild(tooltipObj); var width = tooltipObj.offsetWidth; var height = tooltipObj.offsetHeight; /** * Set the width on the tooltip so it doesn't resize if the window is resized */ tooltipObj.style.width = width + 'px'; tooltipObj.style.top = (y - height - 2) + 'px'; /** * If the function exists call the object specific tooltip positioning function */ if (typeof(obj.positionTooltip) == 'function') { if (tooltipObj.innerHTML.length > 0) { obj.positionTooltip(obj, x, y, tooltipObj, origIdx ? origIdx : idx); if (obj.Get('chart.tooltips.coords.page')) { tooltipObj.style.left = e.pageX - (width / 2) - 4.25 + 'px'; tooltipObj.style.top = e.pageY - height - 10 + 'px'; document.getElementById('__rgraph_tooltip_pointer__').style.left = (parseInt(tooltipObj.offsetWidth) / 2) - 8.5 + 'px'; } } } else { tooltipObj.style.left = e.pageX - (width / 2) - 4.25 + 'px'; tooltipObj.style.top = e.pageY - height - 7 + 'px'; } if (effect == 'fade' || effect == 'expand' || effect == 'contract' || effect == 'snap') { setTimeout(function () {tooltipObj.style.opacity = 0.1;}, 25); setTimeout(function () {tooltipObj.style.opacity = 0.2;}, 50); setTimeout(function () {tooltipObj.style.opacity = 0.3;}, 75); setTimeout(function () {tooltipObj.style.opacity = 0.4;}, 100); setTimeout(function () {tooltipObj.style.opacity = 0.5;}, 125); setTimeout(function () {tooltipObj.style.opacity = 0.6;}, 150); setTimeout(function () {tooltipObj.style.opacity = 0.7;}, 175); setTimeout(function () {tooltipObj.style.opacity = 0.8;}, 200); setTimeout(function () {tooltipObj.style.opacity = 0.9;}, 225); if (effect == 'expand' || effect == 'contract' || effect == 'snap') { console.log('[RGRAPH] The snap, expand and contract tooltip effects are deprecated. Available effects now are fade and none'); } } setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.opacity = 1;}", effect == 'none' ? 50 : 250); /** * If the tooltip it self is clicked, cancel it */ tooltipObj.onmousedown = function (e){e.stopPropagation();} tooltipObj.onmouseup = function (e){e.stopPropagation();} tooltipObj.onclick = function (e){if (e.button == 0) {e.stopPropagation();}} /** * Keep a reference to the tooltip in the registry */ RGraph.Registry.Set('chart.tooltip', tooltipObj); /** * Fire the tooltip event */ RG.FireCustomEvent(obj, 'ontooltip'); }; /** * */ RG.getTooltipTextFromDIV = function (text) { // This regex is duplicated firher down on roughly line 888 var result = /^id:(.*)/.exec(text); if (result && result[1] && document.getElementById(result[1])) { text = document.getElementById(result[1]).innerHTML; } else if (result && result[1]) { text = ''; } return text; }; /** * */ RG.getTooltipWidth = function (text, obj) { var div = document.createElement('DIV'); div.className = obj.Get('chart.tooltips.css.class'); div.style.paddingLeft = RGraph.tooltips.padding; div.style.paddingRight = RGraph.tooltips.padding; div.style.fontFamily = RGraph.tooltips.font_face; div.style.fontSize = RGraph.tooltips.font_size; div.style.visibility = 'hidden'; div.style.position = 'absolute'; div.style.top = '300px'; div.style.left = 0; div.style.display = 'inline'; div.innerHTML = RGraph.getTooltipTextFromDIV(text); document.body.appendChild(div); return div.offsetWidth; }; /** * Hides the currently shown tooltip */ RG.hideTooltip = RG.HideTooltip = function () { var tooltip = RGraph.Registry.Get('chart.tooltip'); var uid = arguments[0] && arguments[0].uid ? arguments[0].uid : null; if (tooltip && tooltip.parentNode && (!uid || uid == tooltip.__canvas__.uid)) { tooltip.parentNode.removeChild(tooltip); tooltip.style.display = 'none'; tooltip.style.visibility = 'hidden'; RGraph.Registry.Set('chart.tooltip', null); } }; /** * This installs the window mousedown event listener. It clears any highlight that may * be present. * * @param object obj The chart object * RGraph.InstallWindowMousedownTooltipListener = function (obj) { if (RGraph.Registry.Get('__rgraph_event_listeners__')['window_mousedown']) { return; } // When the canvas is cleared, reset this flag so that the event listener is installed again RGraph.AddCustomEventListener(obj, 'onclear', function (obj) {RGraph.Registry.Get('__rgraph_event_listeners__')['window_mousedown'] = false;}) // NOTE: Global on purpose rgraph_window_mousedown = function (e) { if (RGraph.Registry.Get('chart.tooltip')) { var obj = RGraph.Registry.Get('chart.tooltip').__object__; var canvas = obj.canvas; /** * Get rid of the tooltip and redraw all canvases on the page * RGraph.HideTooltip(); /** * No need to clear if highlighting is disabled * * TODO Really, need to check ALL of the pertinent objects that * are drawing on the canvas using the ObjectRegistry - * ie RGraph.ObjectRegistry.getObjectsByCanvasID() * if (obj.Get('chart.tooltips.highlight')) { RGraph.RedrawCanvas(canvas); } } } window.addEventListener('mousedown', rgraph_window_mousedown, false); RGraph.AddEventListener('window_' + obj.id, 'mousedown', rgraph_window_mousedown); } */ /** * This installs the canvas mouseup event listener. This is the function that * actually shows the appropriate (if any) tooltip. * * @param object obj The chart object * RGraph.InstallCanvasMouseupTooltipListener = function (obj) { if (RGraph.Registry.Get('__rgraph_event_listeners__')[obj.canvas.id + '_mouseup']) { return; } RGraph.Registry.Get('__rgraph_event_listeners__')[obj.canvas.id + '_mouseup'] = true; // When the canvas is cleared, reset this flag so that the event listener is installed again RGraph.AddCustomEventListener(obj, 'onclear', function (obj) {RGraph.Registry.Get('__rgraph_event_listeners__')[obj.canvas.id + '_mouseup'] = false}); // Install the onclick event handler for the tooltips // // // NOTE: Global on purpose rgraph_canvas_mouseup_func = function (e) { var x = arguments[1] ? arguments[1] : e.pageX; var y = arguments[2] ? arguments[2] : e.pageY; var objects = RGraph.ObjectRegistry.getObjectsByCanvasID(e.target.id); // It's important to go backwards through the array so that the front charts // are checked first, then the charts at the back for (var i=(objects.length - 1); i>=0; --i) { var shape = objects[i].getShape(e); if (shape && shape['object'] && !RGraph.Registry.Get('chart.tooltip')) { /** * This allows the Scatter chart funky tooltips style * if (objects[i].type == 'scatter' && shape['dataset'] > 0) { for (var j=0; j<(objects[i].data.length - 1); ++j) { shape['index'] += objects[i].data[j].length; } } var text = RGraph.parseTooltipText(objects[i].Get('chart.tooltips'), shape['index']); if (text) { if (shape['object'].Get('chart.tooltips.hotspot.xonly')) { var canvasXY = RGraph.getCanvasXY(objects[i].canvas); x = canvasXY[0] + shape[1]; y = canvasXY[1] + shape[2]; } RGraph.Tooltip(objects[i], text, x, y, shape['index']); objects[i].Highlight(shape); e.stopPropagation(); e.cancelBubble = true; return false; } } } } obj.canvas.addEventListener('mouseup', rgraph_canvas_mouseup_func, false); RGraph.AddEventListener(obj.id, 'mouseup', rgraph_canvas_mouseup_func); } */ /** * This installs the canvas mousemove event listener. This is the function that * changes the mouse pointer if need be. * * @param object obj The chart object * RGraph.InstallCanvasMousemoveTooltipListener = function (obj) { if (RGraph.Registry.Get('__rgraph_event_listeners__')[obj.canvas.id + '_mousemove']) { return; } RGraph.Registry.Get('__rgraph_event_listeners__')[obj.canvas.id + '_mousemove'] = true; // When the canvas is cleared, reset this flag so that the event listener is installed again RGraph.AddCustomEventListener(obj, 'onclear', function (obj) {RGraph.Registry.Get('__rgraph_event_listeners__')[obj.canvas.id + '_mousemove'] = false}) // Install the mousemove event handler for the tooltips // // NOTE: Global on purpose rgraph_canvas_mousemove_func = function (e) { var objects = RGraph.ObjectRegistry.getObjectsByCanvasID(e.target.id); for (var i=0; i 0) { for (var j=0; j<(objects[i].data.length - 1); ++j) { shape['index'] += objects[i].data[j].length; } } var text = RGraph.parseTooltipText(objects[i].Get('chart.tooltips'), shape['index']); if (text) { e.target.style.cursor = 'pointer'; /** * This facilitates the event triggering the tooltips being mousemove * if ( typeof(objects[i].Get('chart.tooltips.event')) == 'string' && objects[i].Get('chart.tooltips.event') == 'onmousemove' && (!RGraph.Registry.Get('chart.tooltip') || shape['index'] != RGraph.Registry.Get('chart.tooltip').__index__ || shape['object'].uid != RGraph.Registry.Get('chart.tooltip').__object__.uid) ) { // Hide any current tooltip rgraph_window_mousedown(e); rgraph_canvas_mouseup_func(e); } } } } } obj.canvas.addEventListener('mousemove', rgraph_canvas_mousemove_func, false); RGraph.AddEventListener(obj.id, 'mousemove', rgraph_canvas_mousemove_func); } */ /** * This (as the name suggests preloads any images it can find in the tooltip text * * @param object obj The chart object */ RG.preLoadTooltipImages = RG.PreLoadTooltipImages = function (obj) { var tooltips = obj.Get('chart.tooltips'); if (RGraph.hasTooltips(obj)) { if (obj.type == 'rscatter') { tooltips = []; for (var i=0; i