src/pyams_skin/resources/js/ext/flot/jquery.flot.hover.js
changeset 566 a1707c607eec
parent 565 318533413200
child 567 bca1726b1d85
equal deleted inserted replaced
565:318533413200 566:a1707c607eec
     1 /* global jQuery */
       
     2 
       
     3 /**
       
     4 ## jquery.flot.hover.js
       
     5 
       
     6 This plugin is used for mouse hover and tap on a point of plot series.
       
     7 It supports the following options:
       
     8 ```js
       
     9 grid: {
       
    10     hoverable: false, //to trigger plothover event on mouse hover or tap on a point
       
    11     clickable: false //to trigger plotclick event on mouse hover
       
    12 }
       
    13 ```
       
    14 
       
    15 It listens to native mouse move event or click, as well as artificial generated
       
    16 tap and touchevent.
       
    17 
       
    18 When the mouse is over a point or a tap on a point is performed, that point or
       
    19 the correscponding bar will be highlighted and a "plothover" event will be generated.
       
    20 
       
    21 Custom "touchevent" is triggered when any touch interaction is made. Hover plugin
       
    22 handles this events by unhighlighting all of the previously highlighted points and generates
       
    23 "plothovercleanup" event to notify any part that is handling plothover (for exemple to cleanup
       
    24 the tooltip from webcharts).
       
    25 */
       
    26 
       
    27 (function($) {
       
    28     'use strict';
       
    29 
       
    30     var options = {
       
    31         grid: {
       
    32             hoverable: false,
       
    33             clickable: false
       
    34         }
       
    35     };
       
    36 
       
    37     var browser = $.plot.browser;
       
    38 
       
    39     var eventType = {
       
    40         click: 'click',
       
    41         hover: 'hover'
       
    42     }
       
    43 
       
    44     function init(plot) {
       
    45         var lastMouseMoveEvent;
       
    46         var highlights = [];
       
    47 
       
    48         function bindEvents(plot, eventHolder) {
       
    49             var o = plot.getOptions();
       
    50 
       
    51             if (o.grid.hoverable || o.grid.clickable) {
       
    52                 eventHolder[0].addEventListener('touchevent', triggerCleanupEvent, false);
       
    53                 eventHolder[0].addEventListener('tap', generatePlothoverEvent, false);
       
    54             }
       
    55 
       
    56             if (o.grid.clickable) {
       
    57                 eventHolder.bind("click", onClick);
       
    58             }
       
    59 
       
    60             if (o.grid.hoverable) {
       
    61                 eventHolder.bind("mousemove", onMouseMove);
       
    62 
       
    63                 // Use bind, rather than .mouseleave, because we officially
       
    64                 // still support jQuery 1.2.6, which doesn't define a shortcut
       
    65                 // for mouseenter or mouseleave.  This was a bug/oversight that
       
    66                 // was fixed somewhere around 1.3.x.  We can return to using
       
    67                 // .mouseleave when we drop support for 1.2.6.
       
    68 
       
    69                 eventHolder.bind("mouseleave", onMouseLeave);
       
    70             }
       
    71         }
       
    72 
       
    73         function shutdown(plot, eventHolder) {
       
    74             eventHolder[0].removeEventListener('tap', generatePlothoverEvent);
       
    75             eventHolder[0].removeEventListener('touchevent', triggerCleanupEvent);
       
    76             eventHolder.unbind("mousemove", onMouseMove);
       
    77             eventHolder.unbind("mouseleave", onMouseLeave);
       
    78             eventHolder.unbind("click", onClick);
       
    79             highlights = [];
       
    80         }
       
    81 
       
    82 
       
    83         function generatePlothoverEvent(e) {
       
    84             var o = plot.getOptions(),
       
    85                 newEvent = new CustomEvent('mouseevent');
       
    86 
       
    87             //transform from touch event to mouse event format
       
    88             newEvent.pageX = e.detail.changedTouches[0].pageX;
       
    89             newEvent.pageY = e.detail.changedTouches[0].pageY;
       
    90             newEvent.clientX = e.detail.changedTouches[0].clientX;
       
    91             newEvent.clientY = e.detail.changedTouches[0].clientY;
       
    92 
       
    93             if (o.grid.hoverable) {
       
    94                 doTriggerClickHoverEvent(newEvent, eventType.hover, 30);
       
    95             }
       
    96             return false;
       
    97         }
       
    98 
       
    99         function doTriggerClickHoverEvent(event, eventType, searchDistance) {
       
   100             var series = plot.getData();
       
   101             if (event !== undefined
       
   102                 && series.length > 0
       
   103                 && series[0].xaxis.c2p !== undefined
       
   104                 && series[0].yaxis.c2p !== undefined) {
       
   105                 var eventToTrigger = "plot" + eventType;
       
   106                 var seriesFlag = eventType + "able";
       
   107                 triggerClickHoverEvent(eventToTrigger, event,
       
   108                     function(i) {
       
   109                         return series[i][seriesFlag] !== false;
       
   110                     }, searchDistance);
       
   111             }
       
   112         }
       
   113 
       
   114         function onMouseMove(e) {
       
   115             lastMouseMoveEvent = e;
       
   116             plot.getPlaceholder()[0].lastMouseMoveEvent = e;
       
   117             doTriggerClickHoverEvent(e, eventType.hover);
       
   118         }
       
   119 
       
   120         function onMouseLeave(e) {
       
   121             lastMouseMoveEvent = undefined;
       
   122             plot.getPlaceholder()[0].lastMouseMoveEvent = undefined;
       
   123             triggerClickHoverEvent("plothover", e,
       
   124                 function(i) {
       
   125                     return false;
       
   126                 });
       
   127         }
       
   128 
       
   129         function onClick(e) {
       
   130             doTriggerClickHoverEvent(e, eventType.click);
       
   131         }
       
   132 
       
   133         function triggerCleanupEvent() {
       
   134             plot.unhighlight();
       
   135             plot.getPlaceholder().trigger('plothovercleanup');
       
   136         }
       
   137 
       
   138         // trigger click or hover event (they send the same parameters
       
   139         // so we share their code)
       
   140         function triggerClickHoverEvent(eventname, event, seriesFilter, searchDistance) {
       
   141             var options = plot.getOptions(),
       
   142                 offset = plot.offset(),
       
   143                 page = browser.getPageXY(event),
       
   144                 canvasX = page.X - offset.left,
       
   145                 canvasY = page.Y - offset.top,
       
   146                 pos = plot.c2p({
       
   147                     left: canvasX,
       
   148                     top: canvasY
       
   149                 }),
       
   150                 distance = searchDistance !== undefined ? searchDistance : options.grid.mouseActiveRadius;
       
   151 
       
   152             pos.pageX = page.X;
       
   153             pos.pageY = page.Y;
       
   154 
       
   155             var item = plot.findNearbyItem(canvasX, canvasY, seriesFilter, distance);
       
   156 
       
   157             if (item) {
       
   158                 // fill in mouse pos for any listeners out there
       
   159                 item.pageX = parseInt(item.series.xaxis.p2c(item.datapoint[0]) + offset.left, 10);
       
   160                 item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top, 10);
       
   161             }
       
   162 
       
   163             if (options.grid.autoHighlight) {
       
   164                 // clear auto-highlights
       
   165                 for (var i = 0; i < highlights.length; ++i) {
       
   166                     var h = highlights[i];
       
   167                     if ((h.auto === eventname &&
       
   168                         !(item && h.series === item.series &&
       
   169                             h.point[0] === item.datapoint[0] &&
       
   170                             h.point[1] === item.datapoint[1])) || !item) {
       
   171                         unhighlight(h.series, h.point);
       
   172                     }
       
   173                 }
       
   174 
       
   175                 if (item) {
       
   176                     highlight(item.series, item.datapoint, eventname);
       
   177                 }
       
   178             }
       
   179 
       
   180             plot.getPlaceholder().trigger(eventname, [pos, item]);
       
   181         }
       
   182 
       
   183         function highlight(s, point, auto) {
       
   184             if (typeof s === "number") {
       
   185                 s = plot.getData()[s];
       
   186             }
       
   187 
       
   188             if (typeof point === "number") {
       
   189                 var ps = s.datapoints.pointsize;
       
   190                 point = s.datapoints.points.slice(ps * point, ps * (point + 1));
       
   191             }
       
   192 
       
   193             var i = indexOfHighlight(s, point);
       
   194             if (i === -1) {
       
   195                 highlights.push({
       
   196                     series: s,
       
   197                     point: point,
       
   198                     auto: auto
       
   199                 });
       
   200 
       
   201                 plot.triggerRedrawOverlay();
       
   202             } else if (!auto) {
       
   203                 highlights[i].auto = false;
       
   204             }
       
   205         }
       
   206 
       
   207         function unhighlight(s, point) {
       
   208             if (s == null && point == null) {
       
   209                 highlights = [];
       
   210                 plot.triggerRedrawOverlay();
       
   211                 return;
       
   212             }
       
   213 
       
   214             if (typeof s === "number") {
       
   215                 s = plot.getData()[s];
       
   216             }
       
   217 
       
   218             if (typeof point === "number") {
       
   219                 var ps = s.datapoints.pointsize;
       
   220                 point = s.datapoints.points.slice(ps * point, ps * (point + 1));
       
   221             }
       
   222 
       
   223             var i = indexOfHighlight(s, point);
       
   224             if (i !== -1) {
       
   225                 highlights.splice(i, 1);
       
   226 
       
   227                 plot.triggerRedrawOverlay();
       
   228             }
       
   229         }
       
   230 
       
   231         function indexOfHighlight(s, p) {
       
   232             for (var i = 0; i < highlights.length; ++i) {
       
   233                 var h = highlights[i];
       
   234                 if (h.series === s &&
       
   235                     h.point[0] === p[0] &&
       
   236                     h.point[1] === p[1]) {
       
   237                     return i;
       
   238                 }
       
   239             }
       
   240 
       
   241             return -1;
       
   242         }
       
   243 
       
   244         function processDatapoints() {
       
   245             triggerCleanupEvent();
       
   246             doTriggerClickHoverEvent(lastMouseMoveEvent, eventType.hover);
       
   247         }
       
   248 
       
   249         function setupGrid() {
       
   250             doTriggerClickHoverEvent(lastMouseMoveEvent, eventType.hover);
       
   251         }
       
   252 
       
   253         function drawOverlay(plot, octx, overlay) {
       
   254             var plotOffset = plot.getPlotOffset(),
       
   255                 i, hi;
       
   256 
       
   257             octx.save();
       
   258             octx.translate(plotOffset.left, plotOffset.top);
       
   259             for (i = 0; i < highlights.length; ++i) {
       
   260                 hi = highlights[i];
       
   261 
       
   262                 if (hi.series.bars.show) drawBarHighlight(hi.series, hi.point, octx);
       
   263                 else drawPointHighlight(hi.series, hi.point, octx, plot);
       
   264             }
       
   265             octx.restore();
       
   266         }
       
   267 
       
   268         function drawPointHighlight(series, point, octx, plot) {
       
   269             var x = point[0],
       
   270                 y = point[1],
       
   271                 axisx = series.xaxis,
       
   272                 axisy = series.yaxis,
       
   273                 highlightColor = (typeof series.highlightColor === "string") ? series.highlightColor : $.color.parse(series.color).scale('a', 0.5).toString();
       
   274 
       
   275             if (x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max) {
       
   276                 return;
       
   277             }
       
   278 
       
   279             var pointRadius = series.points.radius + series.points.lineWidth / 2;
       
   280             octx.lineWidth = pointRadius;
       
   281             octx.strokeStyle = highlightColor;
       
   282             var radius = 1.5 * pointRadius;
       
   283             x = axisx.p2c(x);
       
   284             y = axisy.p2c(y);
       
   285 
       
   286             octx.beginPath();
       
   287             var symbol = series.points.symbol;
       
   288             if (symbol === 'circle') {
       
   289                 octx.arc(x, y, radius, 0, 2 * Math.PI, false);
       
   290             } else if (typeof symbol === 'string' && plot.drawSymbol && plot.drawSymbol[symbol]) {
       
   291                 plot.drawSymbol[symbol](octx, x, y, radius, false);
       
   292             }
       
   293 
       
   294             octx.closePath();
       
   295             octx.stroke();
       
   296         }
       
   297 
       
   298         function drawBarHighlight(series, point, octx) {
       
   299             var highlightColor = (typeof series.highlightColor === "string") ? series.highlightColor : $.color.parse(series.color).scale('a', 0.5).toString(),
       
   300                 fillStyle = highlightColor,
       
   301                 barLeft;
       
   302 
       
   303             var barWidth = series.bars.barWidth[0] || series.bars.barWidth;
       
   304             switch (series.bars.align) {
       
   305                 case "left":
       
   306                     barLeft = 0;
       
   307                     break;
       
   308                 case "right":
       
   309                     barLeft = -barWidth;
       
   310                     break;
       
   311                 default:
       
   312                     barLeft = -barWidth / 2;
       
   313             }
       
   314 
       
   315             octx.lineWidth = series.bars.lineWidth;
       
   316             octx.strokeStyle = highlightColor;
       
   317 
       
   318             var fillTowards = series.bars.fillTowards || 0,
       
   319                 bottom = fillTowards > series.yaxis.min ? Math.min(series.yaxis.max, fillTowards) : series.yaxis.min;
       
   320 
       
   321             $.plot.drawSeries.drawBar(point[0], point[1], point[2] || bottom, barLeft, barLeft + barWidth,
       
   322                 function() {
       
   323                     return fillStyle;
       
   324                 }, series.xaxis, series.yaxis, octx, series.bars.horizontal, series.bars.lineWidth);
       
   325         }
       
   326 
       
   327         function initHover(plot, options) {
       
   328             plot.highlight = highlight;
       
   329             plot.unhighlight = unhighlight;
       
   330             if (options.grid.hoverable || options.grid.clickable) {
       
   331                 plot.hooks.drawOverlay.push(drawOverlay);
       
   332                 plot.hooks.processDatapoints.push(processDatapoints);
       
   333                 plot.hooks.setupGrid.push(setupGrid);
       
   334             }
       
   335 
       
   336             lastMouseMoveEvent = plot.getPlaceholder()[0].lastMouseMoveEvent;
       
   337         }
       
   338 
       
   339         plot.hooks.bindEvents.push(bindEvents);
       
   340         plot.hooks.shutdown.push(shutdown);
       
   341         plot.hooks.processOptions.push(initHover);
       
   342     }
       
   343 
       
   344     $.plot.plugins.push({
       
   345         init: init,
       
   346         options: options,
       
   347         name: 'hover',
       
   348         version: '0.1'
       
   349     });
       
   350 })(jQuery);