UNPKG

api-console-assets

Version:

This repo only exists to publish api console components to npm

546 lines (501 loc) 16 kB
// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: http://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); } else {// Plain browser env mod(CodeMirror); } })(function(CodeMirror) { 'use strict'; var HINT_ELEMENT_CLASS = 'CodeMirror-hint'; var ACTIVE_HINT_ELEMENT_CLASS = 'iron-selected'; // This is the old interface, kept around for now to stay // backwards-compatible. CodeMirror.showHint = function(cm, getHints, options) { if (!getHints) { return cm.showHint(options); } if (options && options.async) { getHints.async = true; } var newOpts = { hint: getHints }; if (options) { for (var prop in options) { newOpts[prop] = options[prop]; } } return cm.showHint(newOpts); }; CodeMirror.defineExtension('showHint', function(options) { // We want a single cursor position. if (this.listSelections().length > 1 || this.somethingSelected()) { return; } if (this.state.completionActive) { this.state.completionActive.close(); } var completion = this.state.completionActive = new Completion(this, options); if (!completion.options.hint) { return; } CodeMirror.signal(this, 'startCompletion', this); completion.update(true); }); function Completion(cm, options) { this.cm = cm; this.options = this.buildOptions(options); this.widget = null; this.debounce = 0; this.tick = 0; this.startPos = this.cm.getCursor(); this.startLen = this.cm.getLine(this.startPos.line).length; var self = this; cm.on('cursorActivity', this.activityFunc = function() { self.cursorActivity(); }); } var requestAnimationFrame = window.requestAnimationFrame || function(fn) { return setTimeout(fn, 1000 / 60); }; var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout; Completion.prototype = { close: function() { if (!this.active()) { return; } this.cm.state.completionActive = null; this.tick = null; this.cm.off('cursorActivity', this.activityFunc); if (this.widget && this.data) { CodeMirror.signal(this.data, 'close'); } if (this.widget) { this.widget.close(); } CodeMirror.signal(this.cm, 'endCompletion', this.cm); }, active: function() { return this.cm.state.completionActive == this; }, pick: function(data, i) { var completion = data.list[i]; if (completion.hint) { completion.hint(this.cm, data, completion); } else { this.cm.replaceRange(getText(completion), completion.from || data.from, completion.to || data.to, 'complete'); } CodeMirror.signal(data, 'pick', completion); this.close(); }, cursorActivity: function() { if (this.debounce) { cancelAnimationFrame(this.debounce); this.debounce = 0; } var pos = this.cm.getCursor(); var line = this.cm.getLine(pos.line); if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch || pos.ch < this.startPos.ch || this.cm.somethingSelected() || (pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) { this.close(); } else { var self = this; this.debounce = requestAnimationFrame(function() { self.update(); }); if (this.widget) { this.widget.disable(); } } }, update: function(first) { if (this.tick == null) { return; } if (this.data) { CodeMirror.signal(this.data, 'update'); } if (!this.options.hint.async) { this.finishUpdate(this.options.hint(this.cm, this.options), first); } else { var myTick = ++this.tick; var self = this; this.options.hint(this.cm, function(data) { if (self.tick == myTick) { self.finishUpdate(data, first); } }, this.options); } }, finishUpdate: function(data, first) { this.data = data; var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle); if (this.widget) { this.widget.close(); } if (data && data.list.length) { if (picked && data.list.length == 1) { this.pick(data, 0); } else { this.widget = new Widget(this, data); CodeMirror.signal(data, 'shown'); } } }, buildOptions: function(options) { var editor = this.cm.options.hintOptions; var out = {}; for (var prop in defaultOptions) { out[prop] = defaultOptions[prop]; } if (editor) { for (var prop in editor) { if (editor[prop] !== undefined) { out[prop] = editor[prop]; } } } if (options) { for (var prop in options) { if (options[prop] !== undefined) { out[prop] = options[prop]; } } } return out; } }; function getText(completion) { if (typeof completion === 'string') { return completion; } else { return completion.text; } } function buildKeyMap(completion, handle) { var baseMap = { Up: function() { handle.moveFocus(-1); }, Down: function() { handle.moveFocus(1); }, PageUp: function() { handle.moveFocus(-handle.menuSize() + 1, true); }, PageDown: function() { handle.moveFocus(handle.menuSize() - 1, true); }, Home: function() { handle.setFocus(0); }, End: function() { handle.setFocus(handle.length - 1); }, Enter: handle.pick, Tab: handle.pick, Esc: handle.close }; var custom = completion.options.customKeys; var ourMap = custom ? {} : baseMap; function addBinding(key, val) { var bound; if (typeof val !== 'string') { bound = function(cm) { return val(cm, handle); }; // This mechanism is deprecated } else if (baseMap.hasOwnProperty(val)) { bound = baseMap[val]; } else { bound = val; } ourMap[key] = bound; } if (custom) { for (var key in custom) { if (custom.hasOwnProperty(key)) { addBinding(key, custom[key]); } } } var extra = completion.options.extraKeys; if (extra) { for (var key in extra) { if (extra.hasOwnProperty(key)) { addBinding(key, extra[key]); } } } return ourMap; } function getHintElement(hintsElement, el) { while (el && el != hintsElement) { if (el.nodeName.toUpperCase() === 'LI' && el.parentNode === hintsElement) { return el; } el = el.parentNode; } } function Widget(completion, data) { this.completion = completion; this.data = data; this.picked = false; var widget = this; var cm = completion.cm; var hints = this.hints = document.createElement('paper-material'); hints.className = 'CodeMirror-hints'; this.selectedHint = data.selectedHint || 0; var container = document.createElement('paper-menu'); container.selected = 0; hints.appendChild(container); hints.elevation = 2; var completions = data.list; for (var i = 0; i < completions.length; ++i) { var elt = container.appendChild(document.createElement('paper-item')); var cur = completions[i]; var className = HINT_ELEMENT_CLASS + (i !== this.selectedHint ? '' : ' ' + ACTIVE_HINT_ELEMENT_CLASS); if (cur.className !== null) { className = cur.className ? cur.className + ' ' + className : className; } elt.className = className; if (cur.render) { cur.render(elt, data, cur); } else { elt.appendChild(document.createTextNode(cur.displayText || getText(cur))); } elt.hintId = i; } if (hints.children[0].children[0].nodeName === 'DIV') { this._indexOffset = 1; } else { this._indexOffset = 0; } var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null, 'local'); var left = pos.left; var top = pos.bottom; var below = true; hints.style.left = left + 'px'; hints.style.top = top + 'px'; // If we're at the edge of the screen, then we want the menu to appear on the left of the // cursor. var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth); var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight); (completion.options.container || document.body).appendChild(hints); var box = hints.getBoundingClientRect(); var overlapY = box.bottom - winH; if (overlapY > 0) { var height = box.bottom - box.top; var curTop = pos.top - (pos.bottom - box.top); if (curTop - height > 0) { // Fits above cursor hints.style.top = (top = pos.top - height) + 'px'; below = false; } else if (height > winH) { hints.style.height = (winH - 5) + 'px'; hints.style.top = (top = pos.bottom - box.top) + 'px'; var cursor = cm.getCursor(); if (data.from.ch != cursor.ch) { pos = cm.cursorCoords(cursor); hints.style.left = (left = pos.left) + 'px'; box = hints.getBoundingClientRect(); } } } var overlapX = box.right - winW; if (overlapX > 0) { if (box.right - box.left > winW) { hints.style.width = (winW - 5) + 'px'; overlapX -= (box.right - box.left) - winW; } hints.style.left = (left = pos.left - overlapX) + 'px'; } cm.addKeyMap(this.keyMap = buildKeyMap(completion, { moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); }, setFocus: function(n) { widget.changeActive(n); }, menuSize: function() { return widget.screenAmount(); }, length: completions.length, close: function() { completion.close(); }, pick: function() { widget.pick(); }, data: data })); if (completion.options.closeOnUnfocus) { var closingOnBlur; cm.on('blur', this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); }); cm.on('focus', this.onFocus = function() { clearTimeout(closingOnBlur); }); } var startScroll = cm.getScrollInfo(); cm.on('scroll', this.onScroll = function() { var curScroll = cm.getScrollInfo(); var editor = cm.getWrapperElement().getBoundingClientRect(); var newTop = top + startScroll.top - curScroll.top; var point = newTop - (window.pageYOffset || (document.documentElement || document.body).scrollTop); if (!below) { point += hints.offsetHeight; } if (point <= editor.top || point >= editor.bottom) { return completion.close(); } hints.style.top = newTop + 'px'; hints.style.left = (left + startScroll.left - curScroll.left) + 'px'; }); CodeMirror.on(hints, 'dblclick', function(e) { var t = getHintElement(hints.children[0], e.target || e.srcElement); if (t && t.hintId != null) { widget.changeActive(t.hintId); widget.pick(); } }); CodeMirror.on(hints, 'click', function(e) { var t = getHintElement(hints.children[0], e.target || e.srcElement); if (t && t.hintId != null) { widget.changeActive(t.hintId); if (completion.options.completeOnSingleClick) { widget.pick(); } } }); CodeMirror.on(hints, 'mousedown', function() { setTimeout(function() { cm.focus(); }, 20); }); CodeMirror.signal(data, 'select', completions[0], hints.children[0].firstChild); return true; } Widget.prototype = { close: function() { if (this.completion.widget != this) { return; } this.completion.widget = null; this.hints.parentNode.removeChild(this.hints); this.completion.cm.removeKeyMap(this.keyMap); var cm = this.completion.cm; if (this.completion.options.closeOnUnfocus) { cm.off('blur', this.onBlur); cm.off('focus', this.onFocus); } cm.off('scroll', this.onScroll); }, disable: function() { this.completion.cm.removeKeyMap(this.keyMap); var widget = this; this.keyMap = { Enter: function() { widget.picked = true; } }; this.completion.cm.addKeyMap(this.keyMap); }, pick: function() { this.completion.pick(this.data, this.selectedHint); }, changeActive: function(i, avoidWrap) { // i += this._indexOffset; if (i >= this.data.list.length) { i = avoidWrap ? this.data.list.length - 1 : 0; } else if (i < 0) { i = avoidWrap ? 0 : this.data.list.length - 1; } if (this.selectedHint === i) { return; } var selectedHint = this.selectedHint + this._indexOffset; var node = this.hints.children[0].children[selectedHint]; node.classList.remove(ACTIVE_HINT_ELEMENT_CLASS); selectedHint = i + this._indexOffset; this.selectedHint = i; node = this.hints.children[0].children[selectedHint]; node.classList.add(ACTIVE_HINT_ELEMENT_CLASS); if (node.offsetTop < this.hints.scrollTop) { this.hints.scrollTop = node.offsetTop - 3; } else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight) { this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3; } CodeMirror.signal(this.data, 'select', this.data.list[selectedHint], node); }, screenAmount: function() { return Math.floor(this.hints.clientHeight / this.hints.children[0].children[0].offsetHeight) || 1; } }; CodeMirror.registerHelper('hint', 'auto', function(cm, options) { var helpers = cm.getHelpers(cm.getCursor(), 'hint'); var words; if (helpers.length) { for (var i = 0; i < helpers.length; i++) { var cur = helpers[i](cm, options); if (cur && cur.list.length) { return cur; } } } else if (words = cm.getHelper(cm.getCursor(), 'hintWords')) { if (words) { return CodeMirror.hint.fromList(cm, { words: words }); } } else if (CodeMirror.hint.anyword) { return CodeMirror.hint.anyword(cm, options); } }); CodeMirror.registerHelper('hint', 'fromList', function(cm, options) { var cur = cm.getCursor(); var token = cm.getTokenAt(cur); var found = []; for (var i = 0; i < options.words.length; i++) { var word = options.words[i]; if (word.slice(0, token.string.length) === token.string) { found.push(word); } } if (found.length) { return { list: found, from: CodeMirror.Pos(cur.line, token.start), to: CodeMirror.Pos(cur.line, token.end) }; } }); CodeMirror.commands.autocomplete = CodeMirror.showHint; var defaultOptions = { hint: CodeMirror.hint.auto, completeSingle: true, alignWithWord: true, closeCharacters: /[\s()\[\]{};:>,]/, closeOnUnfocus: true, completeOnSingleClick: false, container: null, customKeys: null, extraKeys: null }; CodeMirror.defineOption('hintOptions', null); });