123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- // CodeMirror, copyright (c) by Marijn Haverbeke and others
- // Distributed under an MIT license: https://codemirror.net/LICENSE
- ;(function (mod) {
- if (typeof exports == 'object' && typeof module == 'object')
- // CommonJS
- mod(require('../../lib/codemirror'))
- else if (typeof define == 'function' && define.amd)
- // AMD
- define(['../../lib/codemirror'], mod)
- // Plain browser env
- else mod(CodeMirror)
- })(function (CodeMirror) {
- 'use strict'
- CodeMirror.defineExtension('annotateScrollbar', function (options) {
- if (typeof options == 'string') options = { className: options }
- return new Annotation(this, options)
- })
- CodeMirror.defineOption('scrollButtonHeight', 0)
- function Annotation(cm, options) {
- this.cm = cm
- this.options = options
- this.buttonHeight = options.scrollButtonHeight || cm.getOption('scrollButtonHeight')
- this.annotations = []
- this.doRedraw = this.doUpdate = null
- this.div = cm.getWrapperElement().appendChild(document.createElement('div'))
- this.div.style.cssText = 'position: absolute; right: 0; top: 0; z-index: 7; pointer-events: none'
- this.computeScale()
- function scheduleRedraw(delay) {
- clearTimeout(self.doRedraw)
- self.doRedraw = setTimeout(function () {
- self.redraw()
- }, delay)
- }
- var self = this
- cm.on(
- 'refresh',
- (this.resizeHandler = function () {
- clearTimeout(self.doUpdate)
- self.doUpdate = setTimeout(function () {
- if (self.computeScale()) scheduleRedraw(20)
- }, 100)
- })
- )
- cm.on('markerAdded', this.resizeHandler)
- cm.on('markerCleared', this.resizeHandler)
- if (options.listenForChanges !== false)
- cm.on(
- 'changes',
- (this.changeHandler = function () {
- scheduleRedraw(250)
- })
- )
- }
- Annotation.prototype.computeScale = function () {
- var cm = this.cm
- var hScale = (cm.getWrapperElement().clientHeight - cm.display.barHeight - this.buttonHeight * 2) / cm.getScrollerElement().scrollHeight
- if (hScale != this.hScale) {
- this.hScale = hScale
- return true
- }
- }
- Annotation.prototype.update = function (annotations) {
- this.annotations = annotations
- this.redraw()
- }
- Annotation.prototype.redraw = function (compute) {
- if (compute !== false) this.computeScale()
- var cm = this.cm,
- hScale = this.hScale
- var frag = document.createDocumentFragment(),
- anns = this.annotations
- var wrapping = cm.getOption('lineWrapping')
- var singleLineH = wrapping && cm.defaultTextHeight() * 1.5
- var curLine = null,
- curLineObj = null
- function getY(pos, top) {
- if (curLine != pos.line) {
- curLine = pos.line
- curLineObj = cm.getLineHandle(pos.line)
- var visual = cm.getLineHandleVisualStart(curLineObj)
- if (visual != curLineObj) {
- curLine = cm.getLineNumber(visual)
- curLineObj = visual
- }
- }
- if ((curLineObj.widgets && curLineObj.widgets.length) || (wrapping && curLineObj.height > singleLineH)) return cm.charCoords(pos, 'local')[top ? 'top' : 'bottom']
- var topY = cm.heightAtLine(curLineObj, 'local')
- return topY + (top ? 0 : curLineObj.height)
- }
- var lastLine = cm.lastLine()
- if (cm.display.barWidth)
- for (var i = 0, nextTop; i < anns.length; i++) {
- var ann = anns[i]
- if (ann.to.line > lastLine) continue
- var top = nextTop || getY(ann.from, true) * hScale
- var bottom = getY(ann.to, false) * hScale
- while (i < anns.length - 1) {
- if (anns[i + 1].to.line > lastLine) break
- nextTop = getY(anns[i + 1].from, true) * hScale
- if (nextTop > bottom + 0.9) break
- ann = anns[++i]
- bottom = getY(ann.to, false) * hScale
- }
- if (bottom == top) continue
- var height = Math.max(bottom - top, 3)
- var elt = frag.appendChild(document.createElement('div'))
- elt.style.cssText = 'position: absolute; right: 0px; width: ' + Math.max(cm.display.barWidth - 1, 2) + 'px; top: ' + (top + this.buttonHeight) + 'px; height: ' + height + 'px'
- elt.className = this.options.className
- if (ann.id) {
- elt.setAttribute('annotation-id', ann.id)
- }
- }
- this.div.textContent = ''
- this.div.appendChild(frag)
- }
- Annotation.prototype.clear = function () {
- this.cm.off('refresh', this.resizeHandler)
- this.cm.off('markerAdded', this.resizeHandler)
- this.cm.off('markerCleared', this.resizeHandler)
- if (this.changeHandler) this.cm.off('changes', this.changeHandler)
- this.div.parentNode.removeChild(this.div)
- }
- })
|