// o---------------------------------------------------------------------------------o // | This file is part of the RGraph package - you can learn more at: | // | | // | https://www.rgraph.net/license.html | // | | // | RGraph is dual-licensed under the Open Source GPL license. That means that it's | // | free to use and there are no restrictions on what you can use RGraph for! | // | If the GPL license does not suit you however, then there's an inexpensive | // | commercial license option available. See the URL above for more details. | // o---------------------------------------------------------------------------------o // // Initialise the various objects // RGraph = window.RGraph || {isrgraph:true,isRGraph: true,rgraph:true}; // Module pattern (function (win, doc, undefined) { var ua = navigator.userAgent; // // This is the window click event listener. It redraws all canvas tags on the page. // RGraph.installWindowMousedownListener = function (obj) { if (!RGraph.window_mousedown_event_listener) { RGraph.window_mousedown_event_listener = function (e) { // // For firefox add the window.event object // if (navigator.userAgent.indexOf('Firefox') >= 0) win.event = e; var tooltip = RGraph.Registry.get('tooltip'); if ( RGraph.hideTooltip && tooltip && tooltip.__object__.get('tooltipsEffect') !== 'slide' ) { RGraph.clear(RGraph.Registry.get('tooltip').__canvas__); RGraph.redraw(); RGraph.hideTooltip(); } }; win.addEventListener('mousedown', RGraph.window_mousedown_event_listener, false); } }; // // This is the window click event listener. It redraws all canvas tags on the page. // RGraph.installWindowMouseupListener = function (obj) { if (!RGraph.window_mouseup_event_listener) { RGraph.window_mouseup_event_listener = function (e) { // // For firefox add the window.event object // if (navigator.userAgent.indexOf('Firefox') >= 0) win.event = e; // // Stop any annotating that may be going on // if (RGraph.annotating_window_onmouseup) { RGraph.annotating_window_onmouseup(e); return; } // // End adjusting // if (RGraph.Registry.get('adjusting') || RGraph.Registry.get('adjusting.gantt')) { var obj = RGraph.Registry.get('adjusting'); // If it's a line chart update the data_arr variable if (obj && obj.type === 'line') { obj.data_arr = RGraph.arrayLinearize(obj.data); } RGraph.fireCustomEvent(RGraph.Registry.get('adjusting'), 'onadjustend'); } RGraph.Registry.set('adjusting', null); RGraph.Registry.set('adjusting.shape', null); RGraph.Registry.set('adjusting.gantt', null); // ============================================== // Finally, redraw the chart // ============================================== var tags = document.getElementsByTagName('canvas'); for (var i=0; i= 0) window.event = e; // ************************************************************************* // Tooltips // ************************************************************************* // This causes things at the edge of the chart area - eg line chart hotspots - not to fire because the // cursor is out of the chart area var objects = RGraph.ObjectRegistry.getObjectsByXY(e); //var objects = RGraph.ObjectRegistry.getObjectsByCanvasID(e.target.id); if (objects) { for (var i=0,len=objects.length; i= 0) window.event = e; // // Go through all the objects and check them to see if anything needs doing // var objects = RGraph.OR.getObjectsByXY(e); // Necessary to track which objects have had the mouseover // triggered on them var uids = []; if (objects && objects.length > 0) { for (var i=0,len=objects.length; i= obj.coords.key[i][0] && mouseXY[0] <= (obj.coords.key[i][0] + obj.coords.key[i][2]) && mouseXY[1] >= obj.coords.key[i][1] && mouseXY[1] <= (obj.coords.key[i][1] + obj.coords.key[i][3]) ) { RGraph.Registry.set('key-element', obj.coords.key[i]); overkey = true; } if (!overkey) { RGraph.Registry.set('key-element', null); } } } // ================================================================================================ // // This facilitates the onmousemove facility // ================================================================================================ // var func = null; if (!func && typeof obj.onmousemove == 'function') { var func = obj.onmousemove; } // // // if (shape) { var index = shape.sequentialIndex; if (typeof obj['$' + index] === 'object' && typeof obj['$' + index].onmousemove == 'function') { var func2 = obj['$' + index].onmousemove; } } // // This bit saves the current pointer style if there isn't one already saved // if (shape && (typeof func == 'function' || typeof func2 == 'function' || typeof obj.get('link') === 'string')) { if (obj.get('eventsMousemoveRevertto') == null) { obj.set('eventsMousemoveRevertto', e.target.style.cursor); } if (typeof func == 'function') RGraph.custom_events_mousemove_pointer = func(e, shape); if (typeof func2 == 'function') RGraph.custom_events_mousemove_pointer = RGraph.custom_events_mousemove_pointer || func2(e, shape); // Go through the RGraph.events array looking for more // event listeners if ( typeof RGraph.events === 'object' && typeof RGraph.events[obj.uid] === 'object') { for (i in RGraph.events[obj.uid]) { if ( typeof i === 'string' && typeof RGraph.events[obj.uid][i] === 'object' && RGraph.events[obj.uid][i][1] === 'onmousemove' && typeof RGraph.events[obj.uid][i][2] === 'function') { (RGraph.events[obj.uid][i][2])(obj); } } } //return; } else if (typeof obj.get('eventsMousemoveRevertto') == 'string') { RGraph.cursor.push('default'); obj.set('eventsMousemoveRevertto', null); } // ====================================================== // This bit of code facilitates the onmouseover event // ====================================================== var func = null; if (!func && typeof obj.onmouseover === 'function') { func = obj.onmouseover; } // Allow for individually index functions to be specified if (shape) { var index = shape.sequentialIndex; if (typeof obj['$' + index] == 'object' && typeof obj['$' + index].onmouseover == 'function') { var func2 = obj['$' + index].onmouseover; } } else { obj.__mouseover_shape_index__ = null; RGraph.__mouseover_objects__ = []; RGraph.last_mouseover_uid = null; RGraph.last_mouseover_object = null; } if (typeof RGraph.__mouseover_objects__ === 'undefined') { RGraph.__mouseover_objects__ = []; RGraph.last_mouseover_uid = null; RGraph.last_mouseover_object = null; } if (shape) { if ((obj.__mouseover_shape_index__ === shape.index) === false) { obj.__mouseover_shape__ = shape; obj.__mouseover_shape_index__ = shape.index; RGraph.last_mouseover_uid = obj.uid; RGraph.last_mouseover_object = obj; RGraph.__mouseover_objects__.push(obj); if (func) func(e, shape); if (func2) func2(e, shape); // Go through the RGraph.events array looking for more // event listeners if ( typeof RGraph.events === 'object' && typeof RGraph.events[obj.uid] === 'object') { for (i in RGraph.events[obj.uid]) { if ( typeof i === 'string' && typeof RGraph.events[obj.uid][i] === 'object' && RGraph.events[obj.uid][i][1] === 'onmouseover' && typeof RGraph.events[obj.uid][i][2] === 'function') { (RGraph.events[obj.uid][i][2])(obj); } } } } } else { obj.__mouseover_shape_index__ = null; RGraph.__mouseover_objects__ = []; RGraph.last_mouseover_uid = null; RGraph.last_mouseover_object = null; } // ================================================================================================ // // Tooltips // ================================================================================================ // var current_tooltip = RGraph.Registry.get('tooltip'); var tooltips = obj.get('tooltips'); var tooltips_event = obj.get('tooltipsEvent'); if ( shape && (tooltips && tooltips[shape.index] || shape.tooltip) && tooltips_event.indexOf('mousemove') !== -1 && ( RGraph.isNull(current_tooltip) // Is there a tooltip being shown? || obj.uid != current_tooltip.__object__.uid // Same object? || (current_tooltip.__index__ != shape.sequentialIndex) // Same datapiece index? [UPDATE ON 29/10/2019 TO TRY AND MATCH THE sequentialIndex] || (typeof shape.dataset === 'number' && shape.dataset != current_tooltip.__shape__.dataset) // Different dataset index ) ) { RGraph.clear(obj.canvas); RGraph.hideTooltip(); RGraph.redraw(); obj.canvas.rgraph_mouseup_event_listener(e); return; } // ================================================================================================ // // Adjusting // ================================================================================================ // if (obj && obj.get('adjustable')) { obj.adjusting_mousemove(e); } // // This facilitates breaking out of the loop when a shape has been found - // ie the cursor is over a shape an upper chart // if (shape || (obj.overChartArea && obj.overChartArea(e) )) { break; } } // // For all objects that are NOT mouseover'ed, reset the // mouseover flag back to null // var objects = RGraph.OR.getObjectsByCanvasID(e.target.id); for (var i=0; i= 0) window.event = e; // // Annotating // if (e.target.__object__ && e.target.__object__.get('annotatable') && RGraph.annotating_canvas_onmousedown) { RGraph.annotating_canvas_onmousedown(e); return; } var obj = RGraph.ObjectRegistry.getObjectByXY(e); if (obj) { var id = obj.id; // // Handle adjusting for all object types // if (obj && obj.isRGraph && obj.get('adjustable')) { // // Check the cursor is in the correct area // var obj = RGraph.OR.getObjectByXY(e); if (obj && obj.isRGraph) { // If applicable, get the appropriate shape and store it in the registry switch (obj.type) { case 'bar': var shape = obj.getShapeByX(e); break; case 'gantt': var shape = obj.getShape(e); if (shape) { var data = typeof obj.data[shape.dataset] === 'object' && obj.data[shape.dataset][shape.index] && obj.data[shape.dataset][shape.index].start ? obj.data[shape.dataset][shape.index] : obj.data[shape.dataset]; var mouseXY = RGraph.getMouseXY(e); RGraph.Registry.set('adjusting.gantt', { dataset: shape.dataset, index: shape.index, object: obj, mousex: mouseXY[0], mousey: mouseXY[1], event: data, event_start: data.start, event_duration: data.duration, mode: (mouseXY[0] > (shape.x + shape.width - 5) ? 'resize' : 'move'), shape: shape }); } break; case 'line': var shape = obj.getShape(e); break; case 'scatter': var shape = obj.getShape(e); break; case 'hbar': var shape = obj.getShapeByY(e); break; case 'activity': var shape = obj.getShape(e); break; default: var shape = null; } // Facilitate one click adjusting on the lline chart if (obj.type === 'line' && obj.properties.adjustableXonly) { var shape = obj.getShapeByX(e); } // // Added 30/9/2016 // Now check the index in the adjustingOnly property // If that property is an object and the appropriate index is // truthy then allow adjusting, otherwise don't. // if ( RGraph.isNull(obj.properties.adjustableOnly) || typeof obj.properties.adjustableOnly === 'undefined' || ( RGraph.isArray(obj.properties.adjustableOnly) && obj.isAdjustable && obj.isAdjustable(shape) ) ) { RGraph.Registry.set('adjusting.shape', shape); // Fire the onadjustbegin event RGraph.fireCustomEvent(obj, 'onadjustbegin'); RGraph.Registry.set('adjusting', obj); // Liberally redraw the canvas RGraph.clear(obj.canvas); RGraph.redraw(); // Call the mousemove event listener so that the canvas // is adjusted even though the mouse isn't moved obj.canvas.rgraph_mousemove_event_listener(e); } } } if (obj.properties.tooltipsEffect !== 'slide') { RGraph.clear(obj.canvas); RGraph.redraw(); } } }; obj.canvas.addEventListener('mousedown', obj.canvas.rgraph_mousedown_event_listener, false); } }; // // This is the canvas click event listener. Used by the pseudo event listener // // @param object obj The chart object // RGraph.installCanvasClickListener = function (obj) { if (!obj.canvas.rgraph_click_event_listener) { obj.canvas.rgraph_click_event_listener = function (e) { // // For firefox add the window.event object // if (navigator.userAgent.indexOf('Firefox') >= 0) window.event = e; var objects = RGraph.ObjectRegistry.getObjectsByXY(e); for (var i=0,len=objects.length; i obj.coords.key[j][0] && mouseX < (obj.coords.key[j][0] + obj.coords.key[j][2]) && mouseY > obj.coords.key[j][1] && mouseY < (obj.coords.key[j][1] + obj.coords.key[j][3])) { var pointer = true; } } } } // // It can be specified in the user mousemove event - remember it can now // be specified in THREE ways // if (RGraph.custom_events_mousemove_pointer) { var pointer = true; RGraph.custom_events_mousemove_pointer = false; } // // // // var index = shape.object.type == 'scatter' ? shape.index_adjusted : shape.index; // // if (!RGraph.isNull(obj['$' + index]) && typeof obj['$' + index].onmousemove == 'function') { // var str = (obj['$' + index].onmousemove).toString(); // if (str.match(/pointer/) && str.match(/cursor/) && str.match(/style/)) { // var pointer = true; // } // } // } // // // Is the chart resizable? Go through all the objects again // var objects = RGraph.OR.objects.byCanvasID; for (var i=0,len=objects.length; i (e.target.width - 32) && mouseY > (e.target.height - 16)) { pointer = true; } if (pointer) { e.target.style.cursor = 'pointer'; } else if (e.target.style.cursor == 'pointer') { e.target.style.cursor = 'default'; } else { e.target.style.cursor = null; } // ========================================================================= // Resize cursor - check mouseis in bottom left corner and if it is change it // ========================================================================= if (resizable && mouseX >= (e.target.width - 15) && mouseY >= (e.target.height - 15)) { e.target.style.cursor = 'move'; } else if (e.target.style.cursor === 'move') { e.target.style.cursor = 'default'; } // ========================================================================= // Line chart dataset highlighting // ========================================================================= var objects = RGraph.OR.getObjectsByXY(e); for (let i=0; i { dist.push({ index: k, distance: Math.abs(value - v) }); }); dist.sort(function (a, b) { return a.distance - b.distance; }); // Reset the value variable value = obj.scale2.values[dist[0].index]; // Determine the linedash setting if (properties.crosshairsDotted) { var linedash = '[1,3]'; } else if (properties.crosshairsDashed) { var linedash = '[5,5]'; } else { var linedash = '[1,1]'; } // Start drawing on a "fresh" canvas RGraph.redraw(); // Draw a vertical line for the HBar if (obj.type === 'hbar') { // Draw the vertical line if (obj.properties.crosshairsVline) { obj.path( 'b ld % lw % m % % l % % s %', linedash, obj.properties.crosshairsLinewidth, obj.getXCoord(value), obj.marginTop, obj.getXCoord(value), obj.canvas.height - obj.marginBottom, obj.properties.crosshairsColor ); } // Draw the horizontal line if (obj.properties.crosshairsHline) { var [mouseX, mouseY] = RGraph.getMouseXY(e); obj.path( 'b ld % lw % m % % l % % s %', linedash, obj.properties.crosshairsLinewidth, obj.properties.marginLeft, mouseY, obj.canvas.width - obj.properties.marginRight, mouseY, obj.properties.crosshairsColor ); } // Draw a horizontal line for bar/line/scatter/waterfall charts } else { if (obj.properties.crosshairsHline) { obj.path( 'b ld % lw % m % % l % % s %', linedash, obj.properties.crosshairsLinewidth, obj.marginLeft, obj.getYCoord(value), obj.canvas.width - obj.marginRight, obj.getYCoord(value), obj.properties.crosshairsColor ); } // Draw a vertical line if (obj.properties.crosshairsVline) { var [mouseX, mouseY] = RGraph.getMouseXY(e); obj.path( 'b ld % lw % m % % l % % s %', linedash, obj.properties.crosshairsLinewidth, mouseX, obj.properties.marginTop, mouseX, obj.canvas.height - obj.properties.marginBottom, obj.properties.crosshairsColor ); } } } }; RGraph.redrawCanvas(obj.canvas); if ( x >= marginLeft && y >= marginTop && x <= (width - marginRight) && y <= (height - marginBottom) ) { var linewidth = properties.crosshairsLinewidth ? properties.crosshairsLinewidth : 1; obj.context.lineWidth = linewidth ? linewidth : 1; obj.path( 'b ss %', properties.crosshairsColor ); // // The crosshairsSnap option // if (properties.crosshairsSnap && !properties.crosshairsSnapToScale) { // Linear search for the closest point var point = null; var dist = null; var len = null; if (obj.type == 'line') { for (var i=0; i ' + xCoord + '
' + properties.crosshairsCoordsLabelsY + ': ' + yCoord; // Change the color of the labels - don't use // inline styles because of CSP security errors document.getElementById('rgraph_crosshairsCoordsLabelsX').style.color = '#666'; document.getElementById('rgraph_crosshairsCoordsLabelsY').style.color = '#666'; obj.canvas.addEventListener('mouseout', RGraph.hideCrosshairCoords, false); obj.canvas.__crosshairs_labels__ = div; obj.canvas.__crosshairs_x__ = xCoord; obj.canvas.__crosshairs_y__ = yCoord; } else if (properties.crosshairsCoords) { alert('[RGRAPH] Showing crosshair coordinates is only supported on the Scatter chart'); } // // Fire the oncrosshairs custom event // RGraph.fireCustomEvent(obj, 'oncrosshairs'); } else { RGraph.hideCrosshairCoords(); } }; // // Adds a mousemove event listener that highlights a segment based on th // mousemove event. Used in the Rose and the RScatter charts // //@param int segments The number of segments to allow // RGraph.allowSegmentHighlight = function (opt) { var obj = opt.object, count = opt.count, fill = opt.fill, stroke = opt.stroke if (!RGraph.segmentHighlightFunction) { RGraph.segmentHighlightFunction = function (e) { var mouseXY = RGraph.getMouseXY(e); var angle = RGraph.getAngleByXY(obj.centerx, obj.centery, mouseXY[0], mouseXY[1]); angle += RGraph.HALFPI; if (angle > RGraph.TWOPI) { angle -= RGraph.TWOPI; } RGraph.redraw(); var start = 0; var end = 0; var a = (Math.PI * 2) / count; // // Radius // var r = obj.radius; (function () { for (i=0; i