Przeglądaj źródła

Merge pull request #11469 from grafana/jquery-flot-events-to-ts

migrated jquery.flot.events to ts
Marcus Efraimsson 7 lat temu
rodzic
commit
dde484be60

+ 0 - 604
public/app/plugins/panel/graph/jquery.flot.events.js

@@ -1,604 +0,0 @@
-define([
-  'jquery',
-  'lodash',
-  'angular',
-  'tether-drop',
-],
-function ($, _, angular, Drop) {
-  'use strict';
-
-  function createAnnotationToolip(element, event, plot) {
-    var injector = angular.element(document).injector();
-    var content = document.createElement('div');
-    content.innerHTML = '<annotation-tooltip event="event" on-edit="onEdit()"></annotation-tooltip>';
-
-    injector.invoke(["$compile", "$rootScope", function($compile, $rootScope) {
-      var eventManager = plot.getOptions().events.manager;
-      var tmpScope = $rootScope.$new(true);
-      tmpScope.event = event;
-      tmpScope.onEdit = function() {
-        eventManager.editEvent(event);
-      };
-
-      $compile(content)(tmpScope);
-      tmpScope.$digest();
-      tmpScope.$destroy();
-
-      var drop = new Drop({
-        target: element[0],
-        content: content,
-        position: "bottom center",
-        classes: 'drop-popover drop-popover--annotation',
-        openOn: 'hover',
-        hoverCloseDelay: 200,
-        tetherOptions: {
-          constraints: [{to: 'window', pin: true, attachment: "both"}]
-        }
-      });
-
-      drop.open();
-
-      drop.on('close', function() {
-        setTimeout(function() {
-          drop.destroy();
-        });
-      });
-    }]);
-  }
-
-  var markerElementToAttachTo = null;
-
-  function createEditPopover(element, event, plot) {
-    var eventManager = plot.getOptions().events.manager;
-    if (eventManager.editorOpen) {
-      // update marker element to attach to (needed in case of legend on the right
-      // when there is a double render pass and the initial marker element is removed)
-      markerElementToAttachTo = element;
-      return;
-    }
-
-    // mark as openend
-    eventManager.editorOpened();
-    // set marker element to attache to
-    markerElementToAttachTo = element;
-
-    // wait for element to be attached and positioned
-    setTimeout(function() {
-
-      var injector = angular.element(document).injector();
-      var content = document.createElement('div');
-      content.innerHTML = '<event-editor panel-ctrl="panelCtrl" event="event" close="close()"></event-editor>';
-
-      injector.invoke(["$compile", "$rootScope", function($compile, $rootScope) {
-        var scope = $rootScope.$new(true);
-        var drop;
-
-        scope.event = event;
-        scope.panelCtrl = eventManager.panelCtrl;
-        scope.close = function() {
-          drop.close();
-        };
-
-        $compile(content)(scope);
-        scope.$digest();
-
-        drop = new Drop({
-          target: markerElementToAttachTo[0],
-          content: content,
-          position: "bottom center",
-          classes: 'drop-popover drop-popover--form',
-          openOn: 'click',
-          tetherOptions: {
-            constraints: [{to: 'window', pin: true, attachment: "both"}]
-          }
-        });
-
-        drop.open();
-        eventManager.editorOpened();
-
-        drop.on('close', function() {
-          // need timeout here in order call drop.destroy
-          setTimeout(function() {
-            eventManager.editorClosed();
-            scope.$destroy();
-            drop.destroy();
-          });
-        });
-      }]);
-
-    }, 100);
-  }
-
-  /*
-   * jquery.flot.events
-   *
-   * description: Flot plugin for adding events/markers to the plot
-   * version: 0.2.5
-   * authors:
-   *    Alexander Wunschik <alex@wunschik.net>
-   *    Joel Oughton <joeloughton@gmail.com>
-   *    Nicolas Joseph <www.nicolasjoseph.com>
-   *
-   * website: https://github.com/mojoaxel/flot-events
-   *
-   * released under MIT License and GPLv2+
-   */
-
-  /**
-   * A class that allows for the drawing an remove of some object
-   */
-  var DrawableEvent = function(object, drawFunc, clearFunc, moveFunc, left, top, width, height) {
-    var _object = object;
-    var	_drawFunc = drawFunc;
-    var	_clearFunc = clearFunc;
-    var	_moveFunc = moveFunc;
-    var	_position = { left: left, top: top };
-    var	_width = width;
-    var	_height = height;
-
-    this.width = function() { return _width; };
-    this.height = function() { return _height; };
-    this.position = function() { return _position; };
-    this.draw = function() { _drawFunc(_object); };
-    this.clear = function() { _clearFunc(_object); };
-    this.getObject = function() { return _object; };
-    this.moveTo = function(position) {
-      _position = position;
-      _moveFunc(_object, _position);
-    };
-  };
-
-  /**
-   * Event class that stores options (eventType, min, max, title, description) and the object to draw.
-   */
-  var VisualEvent = function(options, drawableEvent) {
-    var _parent;
-    var _options = options;
-    var _drawableEvent = drawableEvent;
-    var _hidden = false;
-
-    this.visual = function() { return _drawableEvent; };
-    this.getOptions = function() { return _options; };
-    this.getParent = function() { return _parent; };
-    this.isHidden = function() { return _hidden; };
-    this.hide = function() { _hidden = true; };
-    this.unhide = function() { _hidden = false; };
-  };
-
-  /**
-   * A Class that handles the event-markers inside the given plot
-   */
-  var EventMarkers = function(plot) {
-    var _events = [];
-
-    this._types = [];
-    this._plot = plot;
-    this.eventsEnabled = false;
-
-    this.getEvents = function() {
-      return _events;
-    };
-
-    this.setTypes = function(types) {
-      return this._types = types;
-    };
-
-    /**
-     * create internal objects for the given events
-     */
-    this.setupEvents = function(events) {
-      var that = this;
-      var parts = _.partition(events, 'isRegion');
-      var regions = parts[0];
-      events = parts[1];
-
-      $.each(events, function(index, event) {
-        var ve = new VisualEvent(event, that._buildDiv(event));
-        _events.push(ve);
-      });
-
-      $.each(regions, function (index, event) {
-        var vre = new VisualEvent(event, that._buildRegDiv(event));
-        _events.push(vre);
-      });
-
-      _events.sort(function(a, b) {
-        var ao = a.getOptions(), bo = b.getOptions();
-        if (ao.min > bo.min) { return 1; }
-        if (ao.min < bo.min) { return -1; }
-        return 0;
-      });
-    };
-
-    /**
-     * draw the events to the plot
-     */
-    this.drawEvents = function() {
-      var that = this;
-      // var o = this._plot.getPlotOffset();
-
-      $.each(_events, function(index, event) {
-        // check event is inside the graph range
-        if (that._insidePlot(event.getOptions().min) && !event.isHidden()) {
-          event.visual().draw();
-        }  else {
-          event.visual().getObject().hide();
-        }
-      });
-    };
-
-    /**
-     * update the position of the event-markers (e.g. after scrolling or zooming)
-     */
-    this.updateEvents = function() {
-      var that = this;
-      var o = this._plot.getPlotOffset(), left, top;
-      var xaxis = this._plot.getXAxes()[this._plot.getOptions().events.xaxis - 1];
-
-      $.each(_events, function(index, event) {
-        top = o.top + that._plot.height() - event.visual().height();
-        left = xaxis.p2c(event.getOptions().min) + o.left - event.visual().width() / 2;
-        event.visual().moveTo({ top: top, left: left });
-      });
-    };
-
-    /**
-     * remove all events from the plot
-     */
-    this._clearEvents = function() {
-      $.each(_events, function(index, val) {
-        val.visual().clear();
-      });
-      _events = [];
-    };
-
-    /**
-     * create a DOM element for the given event
-     */
-    this._buildDiv = function(event) {
-      var that = this;
-
-      var container = this._plot.getPlaceholder();
-      var o = this._plot.getPlotOffset();
-      var axes = this._plot.getAxes();
-      var xaxis = this._plot.getXAxes()[this._plot.getOptions().events.xaxis - 1];
-      var yaxis, top, left, color, markerSize, markerShow, lineStyle, lineWidth;
-      var markerTooltip;
-
-      // determine the y axis used
-      if (axes.yaxis && axes.yaxis.used) { yaxis = axes.yaxis; }
-      if (axes.yaxis2 && axes.yaxis2.used) { yaxis = axes.yaxis2; }
-
-      // map the eventType to a types object
-      var eventTypeId = event.eventType;
-
-      if (this._types === null || !this._types[eventTypeId] || !this._types[eventTypeId].color) {
-        color = '#666';
-      } else {
-        color = this._types[eventTypeId].color;
-      }
-
-      if (this._types === null || !this._types[eventTypeId] || !this._types[eventTypeId].markerSize) {
-        markerSize = 8; //default marker size
-      } else {
-        markerSize = this._types[eventTypeId].markerSize;
-      }
-
-      if (this._types === null || !this._types[eventTypeId] || this._types[eventTypeId].markerShow === undefined) {
-        markerShow = true;
-      } else {
-        markerShow = this._types[eventTypeId].markerShow;
-      }
-
-      if (this._types === null || !this._types[eventTypeId] || this._types[eventTypeId].markerTooltip === undefined) {
-        markerTooltip = true;
-      } else {
-        markerTooltip = this._types[eventTypeId].markerTooltip;
-      }
-
-      if (this._types == null || !this._types[eventTypeId] || !this._types[eventTypeId].lineStyle) {
-        lineStyle = 'dashed'; //default line style
-      } else {
-        lineStyle = this._types[eventTypeId].lineStyle.toLowerCase();
-      }
-
-      if (this._types == null || !this._types[eventTypeId] || this._types[eventTypeId].lineWidth === undefined) {
-        lineWidth = 1; //default line width
-      } else {
-        lineWidth = this._types[eventTypeId].lineWidth;
-      }
-
-      var topOffset = xaxis.options.eventSectionHeight || 0;
-      topOffset = topOffset / 3;
-
-      top = o.top + this._plot.height() + topOffset;
-      left = xaxis.p2c(event.min) + o.left;
-
-      var line = $('<div class="events_line flot-temp-elem"></div>').css({
-        "position": "absolute",
-        "opacity": 0.8,
-        "left": left + 'px',
-        "top": 8,
-        "width": lineWidth + "px",
-        "height": this._plot.height() + topOffset * 0.8,
-        "border-left-width": lineWidth + "px",
-        "border-left-style": lineStyle,
-        "border-left-color": color,
-        "color": color
-      })
-      .appendTo(container);
-
-      if (markerShow) {
-        var marker = $('<div class="events_marker"></div>').css({
-          "position": "absolute",
-          "left": (-markerSize - Math.round(lineWidth / 2)) + "px",
-          "font-size": 0,
-          "line-height": 0,
-          "width": 0,
-          "height": 0,
-          "border-left": markerSize+"px solid transparent",
-          "border-right": markerSize+"px solid transparent"
-        });
-
-        marker.appendTo(line);
-
-        if (this._types[eventTypeId] && this._types[eventTypeId].position && this._types[eventTypeId].position.toUpperCase() === 'BOTTOM') {
-          marker.css({
-            "top": top-markerSize-8 +"px",
-            "border-top": "none",
-            "border-bottom": markerSize+"px solid " + color
-          });
-        } else {
-          marker.css({
-            "top": "0px",
-            "border-top": markerSize+"px solid " + color,
-            "border-bottom": "none"
-          });
-        }
-
-        marker.data({
-          "event": event
-        });
-
-        var mouseenter = function() {
-          createAnnotationToolip(marker, $(this).data("event"), that._plot);
-        };
-
-        if (event.editModel) {
-          createEditPopover(marker, event.editModel, that._plot);
-        }
-
-        var mouseleave = function() {
-          that._plot.clearSelection();
-        };
-
-        if (markerTooltip) {
-          marker.css({ "cursor": "help" });
-          marker.hover(mouseenter, mouseleave);
-        }
-      }
-
-      var drawableEvent = new DrawableEvent(
-        line,
-        function drawFunc(obj) { obj.show(); },
-        function(obj) { obj.remove(); },
-        function(obj, position) {
-          obj.css({
-            top: position.top,
-            left: position.left
-          });
-        },
-        left,
-        top,
-        line.width(),
-        line.height()
-      );
-
-      return drawableEvent;
-    };
-
-    /**
-     * create a DOM element for the given region
-     */
-    this._buildRegDiv = function (event) {
-      var that = this;
-
-      var container = this._plot.getPlaceholder();
-      var o = this._plot.getPlotOffset();
-      var axes = this._plot.getAxes();
-      var xaxis = this._plot.getXAxes()[this._plot.getOptions().events.xaxis - 1];
-      var yaxis, top, left, lineWidth, regionWidth, lineStyle, color, markerTooltip;
-
-      // determine the y axis used
-      if (axes.yaxis && axes.yaxis.used) { yaxis = axes.yaxis; }
-      if (axes.yaxis2 && axes.yaxis2.used) { yaxis = axes.yaxis2; }
-
-      // map the eventType to a types object
-      var eventTypeId = event.eventType;
-
-      if (this._types === null || !this._types[eventTypeId] || !this._types[eventTypeId].color) {
-        color = '#666';
-      } else {
-        color = this._types[eventTypeId].color;
-      }
-
-      if (this._types === null || !this._types[eventTypeId] || this._types[eventTypeId].markerTooltip === undefined) {
-        markerTooltip = true;
-      } else {
-        markerTooltip = this._types[eventTypeId].markerTooltip;
-      }
-
-      if (this._types == null || !this._types[eventTypeId] || this._types[eventTypeId].lineWidth === undefined) {
-        lineWidth = 1; //default line width
-      } else {
-        lineWidth = this._types[eventTypeId].lineWidth;
-      }
-
-      if (this._types == null || !this._types[eventTypeId] || !this._types[eventTypeId].lineStyle) {
-        lineStyle = 'dashed'; //default line style
-      } else {
-        lineStyle = this._types[eventTypeId].lineStyle.toLowerCase();
-      }
-
-      var topOffset = 2;
-      top = o.top + this._plot.height() + topOffset;
-
-      var timeFrom = Math.min(event.min, event.timeEnd);
-      var timeTo = Math.max(event.min, event.timeEnd);
-      left = xaxis.p2c(timeFrom) + o.left;
-      var right = xaxis.p2c(timeTo) + o.left;
-      regionWidth = right - left;
-
-      _.each([left, right], function(position) {
-        var line = $('<div class="events_line flot-temp-elem"></div>').css({
-          "position": "absolute",
-          "opacity": 0.8,
-          "left": position + 'px',
-          "top": 8,
-          "width": lineWidth + "px",
-          "height": that._plot.height() + topOffset,
-          "border-left-width": lineWidth + "px",
-          "border-left-style": lineStyle,
-          "border-left-color": color,
-          "color": color
-        });
-        line.appendTo(container);
-      });
-
-      var region = $('<div class="events_marker region_marker flot-temp-elem"></div>').css({
-        "position": "absolute",
-        "opacity": 0.5,
-        "left": left + 'px',
-        "top": top,
-        "width": Math.round(regionWidth + lineWidth) + "px",
-        "height": "0.5rem",
-        "border-left-color": color,
-        "color": color,
-        "background-color": color
-      });
-      region.appendTo(container);
-
-      region.data({
-        "event": event
-      });
-
-      var mouseenter = function () {
-        createAnnotationToolip(region, $(this).data("event"), that._plot);
-      };
-
-      if (event.editModel) {
-        createEditPopover(region, event.editModel, that._plot);
-      }
-
-      var mouseleave = function () {
-        that._plot.clearSelection();
-      };
-
-      if (markerTooltip) {
-        region.css({ "cursor": "help" });
-        region.hover(mouseenter, mouseleave);
-      }
-
-      var drawableEvent = new DrawableEvent(
-        region,
-        function drawFunc(obj) { obj.show(); },
-        function (obj) { obj.remove(); },
-        function (obj, position) {
-          obj.css({
-            top: position.top,
-            left: position.left
-          });
-        },
-        left,
-        top,
-        region.width(),
-        region.height()
-      );
-
-      return drawableEvent;
-    };
-
-    /**
-     * check if the event is inside visible range
-     */
-    this._insidePlot = function(x) {
-      var xaxis = this._plot.getXAxes()[this._plot.getOptions().events.xaxis - 1];
-      var xc = xaxis.p2c(x);
-      return xc > 0 && xc < xaxis.p2c(xaxis.max);
-    };
-  };
-
-  /**
-   * initialize the plugin for the given plot
-   */
-  function init(plot) {
-    /*jshint validthis:true */
-    var that = this;
-    var eventMarkers = new EventMarkers(plot);
-
-    plot.getEvents = function() {
-      return eventMarkers._events;
-    };
-
-    plot.hideEvents = function() {
-      $.each(eventMarkers._events, function(index, event) {
-        event.visual().getObject().hide();
-      });
-    };
-
-    plot.showEvents = function() {
-      plot.hideEvents();
-      $.each(eventMarkers._events, function(index, event) {
-        event.hide();
-      });
-
-      that.eventMarkers.drawEvents();
-    };
-
-    // change events on an existing plot
-    plot.setEvents = function(events) {
-      if (eventMarkers.eventsEnabled) {
-        eventMarkers.setupEvents(events);
-      }
-    };
-
-    plot.hooks.processOptions.push(function(plot, options) {
-      // enable the plugin
-      if (options.events.data != null) {
-        eventMarkers.eventsEnabled = true;
-      }
-    });
-
-    plot.hooks.draw.push(function(plot) {
-      var options = plot.getOptions();
-
-      if (eventMarkers.eventsEnabled) {
-        // check for first run
-        if (eventMarkers.getEvents().length < 1) {
-          eventMarkers.setTypes(options.events.types);
-          eventMarkers.setupEvents(options.events.data);
-        } else {
-          eventMarkers.updateEvents();
-        }
-      }
-
-      eventMarkers.drawEvents();
-    });
-  }
-
-  var defaultOptions = {
-    events: {
-      data: null,
-      types: null,
-      xaxis: 1,
-      position: 'BOTTOM'
-    }
-  };
-
-  $.plot.plugins.push({
-    init: init,
-    options: defaultOptions,
-    name: "events",
-    version: "0.2.5"
-  });
-});

+ 671 - 0
public/app/plugins/panel/graph/jquery.flot.events.ts

@@ -0,0 +1,671 @@
+import angular from 'angular';
+import $ from 'jquery';
+import _ from 'lodash';
+import Drop from 'tether-drop';
+
+/** @ngInject */
+export function createAnnotationToolip(element, event, plot) {
+  let injector = angular.element(document).injector();
+  let content = document.createElement('div');
+  content.innerHTML = '<annotation-tooltip event="event" on-edit="onEdit()"></annotation-tooltip>';
+
+  injector.invoke([
+    '$compile',
+    '$rootScope',
+    function($compile, $rootScope) {
+      let eventManager = plot.getOptions().events.manager;
+      let tmpScope = $rootScope.$new(true);
+      tmpScope.event = event;
+      tmpScope.onEdit = function() {
+        eventManager.editEvent(event);
+      };
+
+      $compile(content)(tmpScope);
+      tmpScope.$digest();
+      tmpScope.$destroy();
+
+      let drop = new Drop({
+        target: element[0],
+        content: content,
+        position: 'bottom center',
+        classes: 'drop-popover drop-popover--annotation',
+        openOn: 'hover',
+        hoverCloseDelay: 200,
+        tetherOptions: {
+          constraints: [{ to: 'window', pin: true, attachment: 'both' }],
+        },
+      });
+
+      drop.open();
+
+      drop.on('close', function() {
+        setTimeout(function() {
+          drop.destroy();
+        });
+      });
+    },
+  ]);
+}
+
+let markerElementToAttachTo = null;
+
+/** @ngInject */
+export function createEditPopover(element, event, plot) {
+  let eventManager = plot.getOptions().events.manager;
+  if (eventManager.editorOpen) {
+    // update marker element to attach to (needed in case of legend on the right
+    // when there is a double render pass and the inital marker element is removed)
+    markerElementToAttachTo = element;
+    return;
+  }
+
+  // mark as openend
+  eventManager.editorOpened();
+  // set marker elment to attache to
+  markerElementToAttachTo = element;
+
+  // wait for element to be attached and positioned
+  setTimeout(function() {
+    let injector = angular.element(document).injector();
+    let content = document.createElement('div');
+    content.innerHTML = '<event-editor panel-ctrl="panelCtrl" event="event" close="close()"></event-editor>';
+
+    injector.invoke([
+      '$compile',
+      '$rootScope',
+      function($compile, $rootScope) {
+        let scope = $rootScope.$new(true);
+        let drop;
+
+        scope.event = event;
+        scope.panelCtrl = eventManager.panelCtrl;
+        scope.close = function() {
+          drop.close();
+        };
+
+        $compile(content)(scope);
+        scope.$digest();
+
+        drop = new Drop({
+          target: markerElementToAttachTo[0],
+          content: content,
+          position: 'bottom center',
+          classes: 'drop-popover drop-popover--form',
+          openOn: 'click',
+          tetherOptions: {
+            constraints: [{ to: 'window', pin: true, attachment: 'both' }],
+          },
+        });
+
+        drop.open();
+        eventManager.editorOpened();
+
+        drop.on('close', function() {
+          // need timeout here in order call drop.destroy
+          setTimeout(function() {
+            eventManager.editorClosed();
+            scope.$destroy();
+            drop.destroy();
+          });
+        });
+      },
+    ]);
+  }, 100);
+}
+
+/*
+ * jquery.flot.events
+ *
+ * description: Flot plugin for adding events/markers to the plot
+ * version: 0.2.5
+ * authors:
+ *    Alexander Wunschik <alex@wunschik.net>
+ *    Joel Oughton <joeloughton@gmail.com>
+ *    Nicolas Joseph <www.nicolasjoseph.com>
+ *
+ * website: https://github.com/mojoaxel/flot-events
+ *
+ * released under MIT License and GPLv2+
+ */
+
+/**
+ * A class that allows for the drawing an remove of some object
+ */
+export class DrawableEvent {
+  _object: any;
+  _drawFunc: any;
+  _clearFunc: any;
+  _moveFunc: any;
+  _position: any;
+  _width: any;
+  _height: any;
+
+  /** @ngInject */
+  constructor(object, drawFunc, clearFunc, moveFunc, left, top, width, height) {
+    this._object = object;
+    this._drawFunc = drawFunc;
+    this._clearFunc = clearFunc;
+    this._moveFunc = moveFunc;
+    this._position = { left: left, top: top };
+    this._width = width;
+    this._height = height;
+  }
+
+  width() {
+    return this._width;
+  }
+  height() {
+    return this._height;
+  }
+  position() {
+    return this._position;
+  }
+  draw() {
+    this._drawFunc(this._object);
+  }
+  clear() {
+    this._clearFunc(this._object);
+  }
+  getObject() {
+    return this._object;
+  }
+  moveTo(position) {
+    this._position = position;
+    this._moveFunc(this._object, this._position);
+  }
+}
+
+/**
+ * Event class that stores options (eventType, min, max, title, description) and the object to draw.
+ */
+export class VisualEvent {
+  _parent: any;
+  _options: any;
+  _drawableEvent: any;
+  _hidden: any;
+
+  /** @ngInject */
+  constructor(options, drawableEvent) {
+    this._options = options;
+    this._drawableEvent = drawableEvent;
+    this._hidden = false;
+  }
+
+  visual() {
+    return this._drawableEvent;
+  }
+  getOptions() {
+    return this._options;
+  }
+  getParent() {
+    return this._parent;
+  }
+  isHidden() {
+    return this._hidden;
+  }
+  hide() {
+    this._hidden = true;
+  }
+  unhide() {
+    this._hidden = false;
+  }
+}
+
+/**
+ * A Class that handles the event-markers inside the given plot
+ */
+export class EventMarkers {
+  _events: any;
+  _types: any;
+  _plot: any;
+  eventsEnabled: any;
+
+  /** @ngInject */
+  constructor(plot) {
+    this._events = [];
+    this._types = [];
+    this._plot = plot;
+    this.eventsEnabled = false;
+  }
+
+  getEvents() {
+    return this._events;
+  }
+
+  setTypes(types) {
+    return (this._types = types);
+  }
+
+  /**
+   * create internal objects for the given events
+   */
+  setupEvents(events) {
+    let parts = _.partition(events, 'isRegion');
+    let regions = parts[0];
+    events = parts[1];
+
+    $.each(events, (index, event) => {
+      let ve = new VisualEvent(event, this._buildDiv(event));
+      this._events.push(ve);
+    });
+
+    $.each(regions, (index, event) => {
+      let vre = new VisualEvent(event, this._buildRegDiv(event));
+      this._events.push(vre);
+    });
+
+    this._events.sort((a, b) => {
+      let ao = a.getOptions(),
+        bo = b.getOptions();
+      if (ao.min > bo.min) {
+        return 1;
+      }
+      if (ao.min < bo.min) {
+        return -1;
+      }
+      return 0;
+    });
+  }
+
+  /**
+   * draw the events to the plot
+   */
+  drawEvents() {
+    // var o = this._plot.getPlotOffset();
+
+    $.each(this._events, (index, event) => {
+      // check event is inside the graph range
+      if (this._insidePlot(event.getOptions().min) && !event.isHidden()) {
+        event.visual().draw();
+      } else {
+        event
+          .visual()
+          .getObject()
+          .hide();
+      }
+    });
+  }
+
+  /**
+   * update the position of the event-markers (e.g. after scrolling or zooming)
+   */
+  updateEvents() {
+    let o = this._plot.getPlotOffset(),
+      left,
+      top;
+    let xaxis = this._plot.getXAxes()[this._plot.getOptions().events.xaxis - 1];
+
+    $.each(this._events, (index, event) => {
+      top = o.top + this._plot.height() - event.visual().height();
+      left = xaxis.p2c(event.getOptions().min) + o.left - event.visual().width() / 2;
+      event.visual().moveTo({ top: top, left: left });
+    });
+  }
+
+  /**
+   * remove all events from the plot
+   */
+  _clearEvents() {
+    $.each(this._events, (index, val) => {
+      val.visual().clear();
+    });
+    this._events = [];
+  }
+
+  /**
+   * create a DOM element for the given event
+   */
+  _buildDiv(event) {
+    let that = this;
+
+    let container = this._plot.getPlaceholder();
+    let o = this._plot.getPlotOffset();
+    let xaxis = this._plot.getXAxes()[this._plot.getOptions().events.xaxis - 1];
+    let top, left, color, markerSize, markerShow, lineStyle, lineWidth;
+    let markerTooltip;
+
+    // map the eventType to a types object
+    let eventTypeId = event.eventType;
+
+    if (this._types === null || !this._types[eventTypeId] || !this._types[eventTypeId].color) {
+      color = '#666';
+    } else {
+      color = this._types[eventTypeId].color;
+    }
+
+    if (this._types === null || !this._types[eventTypeId] || !this._types[eventTypeId].markerSize) {
+      markerSize = 8; //default marker size
+    } else {
+      markerSize = this._types[eventTypeId].markerSize;
+    }
+
+    if (this._types === null || !this._types[eventTypeId] || this._types[eventTypeId].markerShow === undefined) {
+      markerShow = true;
+    } else {
+      markerShow = this._types[eventTypeId].markerShow;
+    }
+
+    if (this._types === null || !this._types[eventTypeId] || this._types[eventTypeId].markerTooltip === undefined) {
+      markerTooltip = true;
+    } else {
+      markerTooltip = this._types[eventTypeId].markerTooltip;
+    }
+
+    if (this._types == null || !this._types[eventTypeId] || !this._types[eventTypeId].lineStyle) {
+      lineStyle = 'dashed'; //default line style
+    } else {
+      lineStyle = this._types[eventTypeId].lineStyle.toLowerCase();
+    }
+
+    if (this._types == null || !this._types[eventTypeId] || this._types[eventTypeId].lineWidth === undefined) {
+      lineWidth = 1; //default line width
+    } else {
+      lineWidth = this._types[eventTypeId].lineWidth;
+    }
+
+    let topOffset = xaxis.options.eventSectionHeight || 0;
+    topOffset = topOffset / 3;
+
+    top = o.top + this._plot.height() + topOffset;
+    left = xaxis.p2c(event.min) + o.left;
+
+    let line = $('<div class="events_line flot-temp-elem"></div>')
+      .css({
+        position: 'absolute',
+        opacity: 0.8,
+        left: left + 'px',
+        top: 8,
+        width: lineWidth + 'px',
+        height: this._plot.height() + topOffset * 0.8,
+        'border-left-width': lineWidth + 'px',
+        'border-left-style': lineStyle,
+        'border-left-color': color,
+        color: color,
+      })
+      .appendTo(container);
+
+    if (markerShow) {
+      let marker = $('<div class="events_marker"></div>').css({
+        position: 'absolute',
+        left: -markerSize - Math.round(lineWidth / 2) + 'px',
+        'font-size': 0,
+        'line-height': 0,
+        width: 0,
+        height: 0,
+        'border-left': markerSize + 'px solid transparent',
+        'border-right': markerSize + 'px solid transparent',
+      });
+
+      marker.appendTo(line);
+
+      if (
+        this._types[eventTypeId] &&
+        this._types[eventTypeId].position &&
+        this._types[eventTypeId].position.toUpperCase() === 'BOTTOM'
+      ) {
+        marker.css({
+          top: top - markerSize - 8 + 'px',
+          'border-top': 'none',
+          'border-bottom': markerSize + 'px solid ' + color,
+        });
+      } else {
+        marker.css({
+          top: '0px',
+          'border-top': markerSize + 'px solid ' + color,
+          'border-bottom': 'none',
+        });
+      }
+
+      marker.data({
+        event: event,
+      });
+
+      let mouseenter = function() {
+        createAnnotationToolip(marker, $(this).data('event'), that._plot);
+      };
+
+      if (event.editModel) {
+        createEditPopover(marker, event.editModel, that._plot);
+      }
+
+      let mouseleave = function() {
+        that._plot.clearSelection();
+      };
+
+      if (markerTooltip) {
+        marker.css({ cursor: 'help' });
+        marker.hover(mouseenter, mouseleave);
+      }
+    }
+
+    let drawableEvent = new DrawableEvent(
+      line,
+      function drawFunc(obj) {
+        obj.show();
+      },
+      function(obj) {
+        obj.remove();
+      },
+      function(obj, position) {
+        obj.css({
+          top: position.top,
+          left: position.left,
+        });
+      },
+      left,
+      top,
+      line.width(),
+      line.height()
+    );
+
+    return drawableEvent;
+  }
+
+  /**
+   * create a DOM element for the given region
+   */
+  _buildRegDiv(event) {
+    let that = this;
+
+    let container = this._plot.getPlaceholder();
+    let o = this._plot.getPlotOffset();
+    let xaxis = this._plot.getXAxes()[this._plot.getOptions().events.xaxis - 1];
+    let top, left, lineWidth, regionWidth, lineStyle, color, markerTooltip;
+
+    // map the eventType to a types object
+    let eventTypeId = event.eventType;
+
+    if (this._types === null || !this._types[eventTypeId] || !this._types[eventTypeId].color) {
+      color = '#666';
+    } else {
+      color = this._types[eventTypeId].color;
+    }
+
+    if (this._types === null || !this._types[eventTypeId] || this._types[eventTypeId].markerTooltip === undefined) {
+      markerTooltip = true;
+    } else {
+      markerTooltip = this._types[eventTypeId].markerTooltip;
+    }
+
+    if (this._types == null || !this._types[eventTypeId] || this._types[eventTypeId].lineWidth === undefined) {
+      lineWidth = 1; //default line width
+    } else {
+      lineWidth = this._types[eventTypeId].lineWidth;
+    }
+
+    if (this._types == null || !this._types[eventTypeId] || !this._types[eventTypeId].lineStyle) {
+      lineStyle = 'dashed'; //default line style
+    } else {
+      lineStyle = this._types[eventTypeId].lineStyle.toLowerCase();
+    }
+
+    let topOffset = 2;
+    top = o.top + this._plot.height() + topOffset;
+
+    let timeFrom = Math.min(event.min, event.timeEnd);
+    let timeTo = Math.max(event.min, event.timeEnd);
+    left = xaxis.p2c(timeFrom) + o.left;
+    let right = xaxis.p2c(timeTo) + o.left;
+    regionWidth = right - left;
+
+    _.each([left, right], position => {
+      let line = $('<div class="events_line flot-temp-elem"></div>').css({
+        position: 'absolute',
+        opacity: 0.8,
+        left: position + 'px',
+        top: 8,
+        width: lineWidth + 'px',
+        height: this._plot.height() + topOffset,
+        'border-left-width': lineWidth + 'px',
+        'border-left-style': lineStyle,
+        'border-left-color': color,
+        color: color,
+      });
+      line.appendTo(container);
+    });
+
+    let region = $('<div class="events_marker region_marker flot-temp-elem"></div>').css({
+      position: 'absolute',
+      opacity: 0.5,
+      left: left + 'px',
+      top: top,
+      width: Math.round(regionWidth + lineWidth) + 'px',
+      height: '0.5rem',
+      'border-left-color': color,
+      color: color,
+      'background-color': color,
+    });
+    region.appendTo(container);
+
+    region.data({
+      event: event,
+    });
+
+    let mouseenter = function() {
+      createAnnotationToolip(region, $(this).data('event'), that._plot);
+    };
+
+    if (event.editModel) {
+      createEditPopover(region, event.editModel, that._plot);
+    }
+
+    let mouseleave = function() {
+      that._plot.clearSelection();
+    };
+
+    if (markerTooltip) {
+      region.css({ cursor: 'help' });
+      region.hover(mouseenter, mouseleave);
+    }
+
+    let drawableEvent = new DrawableEvent(
+      region,
+      function drawFunc(obj) {
+        obj.show();
+      },
+      function(obj) {
+        obj.remove();
+      },
+      function(obj, position) {
+        obj.css({
+          top: position.top,
+          left: position.left,
+        });
+      },
+      left,
+      top,
+      region.width(),
+      region.height()
+    );
+
+    return drawableEvent;
+  }
+
+  /**
+   * check if the event is inside visible range
+   */
+  _insidePlot(x) {
+    let xaxis = this._plot.getXAxes()[this._plot.getOptions().events.xaxis - 1];
+    let xc = xaxis.p2c(x);
+    return xc > 0 && xc < xaxis.p2c(xaxis.max);
+  }
+}
+
+/**
+ * initialize the plugin for the given plot
+ */
+
+/** @ngInject */
+export function init(plot) {
+  /*jshint validthis:true */
+  let that = this;
+  let eventMarkers = new EventMarkers(plot);
+
+  plot.getEvents = function() {
+    return eventMarkers._events;
+  };
+
+  plot.hideEvents = function() {
+    $.each(eventMarkers._events, (index, event) => {
+      event
+        .visual()
+        .getObject()
+        .hide();
+    });
+  };
+
+  plot.showEvents = function() {
+    plot.hideEvents();
+    $.each(eventMarkers._events, (index, event) => {
+      event.hide();
+    });
+
+    that.eventMarkers.drawEvents();
+  };
+
+  // change events on an existing plot
+  plot.setEvents = function(events) {
+    if (eventMarkers.eventsEnabled) {
+      eventMarkers.setupEvents(events);
+    }
+  };
+
+  plot.hooks.processOptions.push(function(plot, options) {
+    // enable the plugin
+    if (options.events.data != null) {
+      eventMarkers.eventsEnabled = true;
+    }
+  });
+
+  plot.hooks.draw.push(function(plot) {
+    let options = plot.getOptions();
+
+    if (eventMarkers.eventsEnabled) {
+      // check for first run
+      if (eventMarkers.getEvents().length < 1) {
+        eventMarkers.setTypes(options.events.types);
+        eventMarkers.setupEvents(options.events.data);
+      } else {
+        eventMarkers.updateEvents();
+      }
+    }
+
+    eventMarkers.drawEvents();
+  });
+}
+
+let defaultOptions = {
+  events: {
+    data: null,
+    types: null,
+    xaxis: 1,
+    position: 'BOTTOM',
+  },
+};
+
+$.plot.plugins.push({
+  init: init,
+  options: defaultOptions,
+  name: 'events',
+  version: '0.2.5',
+});