Passed
Push — master ( 0fd7e8...2bd104 )
by Darío
04:14
created

lib/CodeMirror/addon/scroll/annotatescrollbar.js (2 issues)

Labels
Severity
1
// CodeMirror, copyright (c) by Marijn Haverbeke and others
2
// Distributed under an MIT license: http://codemirror.net/LICENSE
3
4
(function(mod) {
5
  if (typeof exports == "object" && typeof module == "object") // CommonJS
6
    mod(require("../../lib/codemirror"));
7
  else if (typeof define == "function" && define.amd) // AMD
8
    define(["../../lib/codemirror"], mod);
9
  else // Plain browser env
10
    mod(CodeMirror);
11
})(function(CodeMirror) {
12
  "use strict";
13
14
  CodeMirror.defineExtension("annotateScrollbar", function(options) {
15
    if (typeof options == "string") options = {className: options};
16
    return new Annotation(this, options);
17
  });
18
19
  CodeMirror.defineOption("scrollButtonHeight", 0);
20
21
  function Annotation(cm, options) {
22
    this.cm = cm;
23
    this.options = options;
24
    this.buttonHeight = options.scrollButtonHeight || cm.getOption("scrollButtonHeight");
25
    this.annotations = [];
26
    this.doRedraw = this.doUpdate = null;
27
    this.div = cm.getWrapperElement().appendChild(document.createElement("div"));
28
    this.div.style.cssText = "position: absolute; right: 0; top: 0; z-index: 7; pointer-events: none";
29
    this.computeScale();
30
31
    function scheduleRedraw(delay) {
32
      clearTimeout(self.doRedraw);
33
      self.doRedraw = setTimeout(function() { self.redraw(); }, delay);
34
    }
35
36
    var self = this;
37
    cm.on("refresh", this.resizeHandler = function() {
38
      clearTimeout(self.doUpdate);
0 ignored issues
show
The variable self is changed as part of the for loop for example by this on line 36. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
39
      self.doUpdate = setTimeout(function() {
40
        if (self.computeScale()) scheduleRedraw(20);
0 ignored issues
show
The variable self is changed as part of the for loop for example by this on line 36. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
41
      }, 100);
42
    });
43
    cm.on("markerAdded", this.resizeHandler);
44
    cm.on("markerCleared", this.resizeHandler);
45
    if (options.listenForChanges !== false)
46
      cm.on("change", this.changeHandler = function() {
47
        scheduleRedraw(250);
48
      });
49
  }
50
51
  Annotation.prototype.computeScale = function() {
52
    var cm = this.cm;
53
    var hScale = (cm.getWrapperElement().clientHeight - cm.display.barHeight - this.buttonHeight * 2) /
54
      cm.heightAtLine(cm.lastLine() + 1, "local");
55
    if (hScale != this.hScale) {
56
      this.hScale = hScale;
57
      return true;
58
    }
59
  };
60
61
  Annotation.prototype.update = function(annotations) {
62
    this.annotations = annotations;
63
    this.redraw();
64
  };
65
66
  Annotation.prototype.redraw = function(compute) {
67
    if (compute !== false) this.computeScale();
68
    var cm = this.cm, hScale = this.hScale;
69
70
    var frag = document.createDocumentFragment(), anns = this.annotations;
71
72
    var wrapping = cm.getOption("lineWrapping");
73
    var singleLineH = wrapping && cm.defaultTextHeight() * 1.5;
74
    var curLine = null, curLineObj = null;
75
    function getY(pos, top) {
76
      if (curLine != pos.line) {
77
        curLine = pos.line;
78
        curLineObj = cm.getLineHandle(curLine);
79
      }
80
      if (wrapping && curLineObj.height > singleLineH)
81
        return cm.charCoords(pos, "local")[top ? "top" : "bottom"];
82
      var topY = cm.heightAtLine(curLineObj, "local");
83
      return topY + (top ? 0 : curLineObj.height);
84
    }
85
86
    if (cm.display.barWidth) for (var i = 0, nextTop; i < anns.length; i++) {
87
      var ann = anns[i];
88
      var top = nextTop || getY(ann.from, true) * hScale;
89
      var bottom = getY(ann.to, false) * hScale;
90
      while (i < anns.length - 1) {
91
        nextTop = getY(anns[i + 1].from, true) * hScale;
92
        if (nextTop > bottom + .9) break;
93
        ann = anns[++i];
94
        bottom = getY(ann.to, false) * hScale;
95
      }
96
      if (bottom == top) continue;
97
      var height = Math.max(bottom - top, 3);
98
99
      var elt = frag.appendChild(document.createElement("div"));
100
      elt.style.cssText = "position: absolute; right: 0px; width: " + Math.max(cm.display.barWidth - 1, 2) + "px; top: "
101
        + (top + this.buttonHeight) + "px; height: " + height + "px";
102
      elt.className = this.options.className;
103
    }
104
    this.div.textContent = "";
105
    this.div.appendChild(frag);
106
  };
107
108
  Annotation.prototype.clear = function() {
109
    this.cm.off("refresh", this.resizeHandler);
110
    this.cm.off("markerAdded", this.resizeHandler);
111
    this.cm.off("markerCleared", this.resizeHandler);
112
    if (this.changeHandler) this.cm.off("change", this.changeHandler);
113
    this.div.parentNode.removeChild(this.div);
114
  };
115
});
116