UNPKG

tern-aui2.0.x

Version:

A Tern plugin adding AlloyUI 2.x support.

168 lines (154 loc) 4.84 kB
(function() { "use strict"; var HOVER_CLASS = " CodeMirror-hover"; function showTooltip(e, content) { var tt = document.createElement("div"); tt.className = "CodeMirror-hover-tooltip"; if (typeof content == "string") { content = document.createTextNode(content); } tt.appendChild(content); document.body.appendChild(tt); function position(e) { if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position); tt.style.top = Math.max(0, e.clientY - tt.offsetHeight - 5) + "px"; tt.style.left = (e.clientX + 5) + "px"; } CodeMirror.on(document, "mousemove", position); position(e); if (tt.style.opacity != null) tt.style.opacity = 1; return tt; } function rm(elt) { if (elt.parentNode) elt.parentNode.removeChild(elt); } function hideTooltip(tt) { if (!tt.parentNode) return; if (tt.style.opacity == null) rm(tt); tt.style.opacity = 0; setTimeout(function() { rm(tt); }, 600); } function showTooltipFor(e, content, node, state, cm) { var tooltip = showTooltip(e, content); function hide() { CodeMirror.off(node, "mouseout", hide); CodeMirror.off(node, "click", hide); node.className = node.className.replace(HOVER_CLASS, ""); if (tooltip) { hideTooltip(tooltip); tooltip = null; } cm.removeKeyMap(state.keyMap); } var poll = setInterval(function() { if (tooltip) for ( var n = node;; n = n.parentNode) { if (n == document.body) return; if (!n) { hide(); break; } } if (!tooltip) return clearInterval(poll); }, 400); CodeMirror.on(node, "mouseout", hide); CodeMirror.on(node, "click", hide); state.keyMap = {Esc: hide}; cm.addKeyMap(state.keyMap); } function TextHoverState(cm, options) { this.options = options; this.timeout = null; if (options.delay) { this.onMouseOver = function(e) { onMouseOverWithDelay(cm, e); }; } else { this.onMouseOver = function(e) { onMouseOver(cm, e); }; } this.keyMap = null; } function parseOptions(cm, options) { if (options instanceof Function) return { getTextHover : options }; if (!options || options === true) options = {}; if (!options.getTextHover) options.getTextHover = cm.getHelper(CodeMirror.Pos(0, 0), "textHover"); if (!options.getTextHover) throw new Error( "Required option 'getTextHover' missing (text-hover addon)"); return options; } function onMouseOverWithDelay(cm, e) { var state = cm.state.textHover, delay = state.options.delay; clearTimeout(state.timeout); if (e.srcElement) { // hack for IE, because e.srcElement failed when it is used in the tiemout function var newE = {srcElement: e.srcElement, clientX : e.clientX, clientY: e.clientY}; e = newE; } state.timeout = setTimeout(function() {onMouseOver(cm, e);}, delay); } function onMouseOver(cm, e) { var node = e.target || e.srcElement; if (node) { var state = cm.state.textHover, data = getTokenAndPosAt(cm, e); var content = state.options.getTextHover(cm, data, e); if (content) { node.className += HOVER_CLASS; if (typeof content == 'function') content(showTooltipFor, data, e, node, state, cm); else showTooltipFor(e, content, node, state, cm); } } } function optionHandler(cm, val, old) { if (old && old != CodeMirror.Init) { CodeMirror.off(cm.getWrapperElement(), "mouseover", cm.state.textHover.onMouseOver); delete cm.state.textHover; } if (val) { var state = cm.state.textHover = new TextHoverState(cm, parseOptions(cm, val)); CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver); } } // When the mouseover fires, the cursor might not actually be over // the character itself yet. These pairs of x,y offsets are used to // probe a few nearby points when no suitable marked range is found. var nearby = [ 0, 0, 0, 5, 0, -5, 5, 0, -5, 0 ]; function getTokenAndPosAt(cm, e) { var node = e.target || e.srcElement, text = node.innerText || node.textContent; for ( var i = 0; i < nearby.length; i += 2) { var pos = cm.coordsChar({ left : e.clientX + nearby[i], top : e.clientY + nearby[i + 1] }); var token = cm.getTokenAt(pos); if (token && token.string === text) { return { token : token, pos : pos }; } } } CodeMirror.defineOption("textHover", false, optionHandler); // deprecated })();