/
usr
/
share
/
nodejs
/
codemirror
/
src
/
input
/
/usr/share/nodejs/codemirror/src/input
mkdir
upload
Name
Size
Mode
Actions
ContentEditableInput.js
19337
0644
edit
dl
rm
indent.js
2757
0644
edit
dl
rm
input.js
5548
0644
edit
dl
rm
keymap.js
6512
0644
edit
dl
rm
keynames.js
1014
0644
edit
dl
rm
movement.js
5090
0644
edit
dl
rm
TextareaInput.js
13921
0644
edit
dl
rm
Edit:
/usr/share/nodejs/codemirror/src/input/TextareaInput.js
(13921B)
import { operation, runInOp } from "../display/operations.js" import { prepareSelection } from "../display/selection.js" import { applyTextInput, copyableRanges, handlePaste, hiddenTextarea, setLastCopied } from "./input.js" import { cursorCoords, posFromMouse } from "../measurement/position_measurement.js" import { eventInWidget } from "../measurement/widgets.js" import { simpleSelection } from "../model/selection.js" import { selectAll, setSelection } from "../model/selection_updates.js" import { captureRightClick, ie, ie_version, ios, mac, mobile, presto, webkit } from "../util/browser.js" import { activeElt, removeChildrenAndAdd, selectInput } from "../util/dom.js" import { e_preventDefault, e_stop, off, on, signalDOMEvent } from "../util/event.js" import { hasSelection } from "../util/feature_detection.js" import { Delayed, sel_dontScroll } from "../util/misc.js" // TEXTAREA INPUT STYLE export default class TextareaInput { constructor(cm) { this.cm = cm // See input.poll and input.reset this.prevInput = "" // Flag that indicates whether we expect input to appear real soon // now (after some event like 'keypress' or 'input') and are // polling intensively. this.pollingFast = false // Self-resetting timeout for the poller this.polling = new Delayed() // Used to work around IE issue with selection being forgotten when focus moves away from textarea this.hasSelection = false this.composing = null } init(display) { let input = this, cm = this.cm this.createField(display) const te = this.textarea display.wrapper.insertBefore(this.wrapper, display.wrapper.firstChild) // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore) if (ios) te.style.width = "0px" on(te, "input", () => { if (ie && ie_version >= 9 && this.hasSelection) this.hasSelection = null input.poll() }) on(te, "paste", e => { if (signalDOMEvent(cm, e) || handlePaste(e, cm)) return cm.state.pasteIncoming = +new Date input.fastPoll() }) function prepareCopyCut(e) { if (signalDOMEvent(cm, e)) return if (cm.somethingSelected()) { setLastCopied({lineWise: false, text: cm.getSelections()}) } else if (!cm.options.lineWiseCopyCut) { return } else { let ranges = copyableRanges(cm) setLastCopied({lineWise: true, text: ranges.text}) if (e.type == "cut") { cm.setSelections(ranges.ranges, null, sel_dontScroll) } else { input.prevInput = "" te.value = ranges.text.join("\n") selectInput(te) } } if (e.type == "cut") cm.state.cutIncoming = +new Date } on(te, "cut", prepareCopyCut) on(te, "copy", prepareCopyCut) on(display.scroller, "paste", e => { if (eventInWidget(display, e) || signalDOMEvent(cm, e)) return if (!te.dispatchEvent) { cm.state.pasteIncoming = +new Date input.focus() return } // Pass the `paste` event to the textarea so it's handled by its event listener. const event = new Event("paste") event.clipboardData = e.clipboardData te.dispatchEvent(event) }) // Prevent normal selection in the editor (we handle our own) on(display.lineSpace, "selectstart", e => { if (!eventInWidget(display, e)) e_preventDefault(e) }) on(te, "compositionstart", () => { let start = cm.getCursor("from") if (input.composing) input.composing.range.clear() input.composing = { start: start, range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"}) } }) on(te, "compositionend", () => { if (input.composing) { input.poll() input.composing.range.clear() input.composing = null } }) } createField(_display) { // Wraps and hides input textarea this.wrapper = hiddenTextarea() // The semihidden textarea that is focused when the editor is // focused, and receives input. this.textarea = this.wrapper.firstChild } screenReaderLabelChanged(label) { // Label for screenreaders, accessibility if(label) { this.textarea.setAttribute('aria-label', label) } else { this.textarea.removeAttribute('aria-label') } } prepareSelection() { // Redraw the selection and/or cursor let cm = this.cm, display = cm.display, doc = cm.doc let result = prepareSelection(cm) // Move the hidden textarea near the cursor to prevent scrolling artifacts if (cm.options.moveInputWithCursor) { let headPos = cursorCoords(cm, doc.sel.primary().head, "div") let wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect() result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10, headPos.top + lineOff.top - wrapOff.top)) result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10, headPos.left + lineOff.left - wrapOff.left)) } return result } showSelection(drawn) { let cm = this.cm, display = cm.display removeChildrenAndAdd(display.cursorDiv, drawn.cursors) removeChildrenAndAdd(display.selectionDiv, drawn.selection) if (drawn.teTop != null) { this.wrapper.style.top = drawn.teTop + "px" this.wrapper.style.left = drawn.teLeft + "px" } } // Reset the input to correspond to the selection (or to be empty, // when not typing and nothing is selected) reset(typing) { if (this.contextMenuPending || this.composing) return let cm = this.cm if (cm.somethingSelected()) { this.prevInput = "" let content = cm.getSelection() this.textarea.value = content if (cm.state.focused) selectInput(this.textarea) if (ie && ie_version >= 9) this.hasSelection = content } else if (!typing) { this.prevInput = this.textarea.value = "" if (ie && ie_version >= 9) this.hasSelection = null } } getField() { return this.textarea } supportsTouch() { return false } focus() { if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) { try { this.textarea.focus() } catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM } } blur() { this.textarea.blur() } resetPosition() { this.wrapper.style.top = this.wrapper.style.left = 0 } receivedFocus() { this.slowPoll() } // Poll for input changes, using the normal rate of polling. This // runs as long as the editor is focused. slowPoll() { if (this.pollingFast) return this.polling.set(this.cm.options.pollInterval, () => { this.poll() if (this.cm.state.focused) this.slowPoll() }) } // When an event has just come in that is likely to add or change // something in the input textarea, we poll faster, to ensure that // the change appears on the screen quickly. fastPoll() { let missed = false, input = this input.pollingFast = true function p() { let changed = input.poll() if (!changed && !missed) {missed = true; input.polling.set(60, p)} else {input.pollingFast = false; input.slowPoll()} } input.polling.set(20, p) } // Read input from the textarea, and update the document to match. // When something is selected, it is present in the textarea, and // selected (unless it is huge, in which case a placeholder is // used). When nothing is selected, the cursor sits after previously // seen text (can be empty), which is stored in prevInput (we must // not reset the textarea when typing, because that breaks IME). poll() { let cm = this.cm, input = this.textarea, prevInput = this.prevInput // Since this is called a *lot*, try to bail out as cheaply as // possible when it is clear that nothing happened. hasSelection // will be the case when there is a lot of text in the textarea, // in which case reading its value would be expensive. if (this.contextMenuPending || !cm.state.focused || (hasSelection(input) && !prevInput && !this.composing) || cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq) return false let text = input.value // If nothing changed, bail. if (text == prevInput && !cm.somethingSelected()) return false // Work around nonsensical selection resetting in IE9/10, and // inexplicable appearance of private area unicode characters on // some key combos in Mac (#2689). if (ie && ie_version >= 9 && this.hasSelection === text || mac && /[\uf700-\uf7ff]/.test(text)) { cm.display.input.reset() return false } if (cm.doc.sel == cm.display.selForContextMenu) { let first = text.charCodeAt(0) if (first == 0x200b && !prevInput) prevInput = "\u200b" if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo") } } // Find the part of the input that is actually new let same = 0, l = Math.min(prevInput.length, text.length) while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same runInOp(cm, () => { applyTextInput(cm, text.slice(same), prevInput.length - same, null, this.composing ? "*compose" : null) // Don't leave long text in the textarea, since it makes further polling slow if (text.length > 1000 || text.indexOf("\n") > -1) input.value = this.prevInput = "" else this.prevInput = text if (this.composing) { this.composing.range.clear() this.composing.range = cm.markText(this.composing.start, cm.getCursor("to"), {className: "CodeMirror-composing"}) } }) return true } ensurePolled() { if (this.pollingFast && this.poll()) this.pollingFast = false } onKeyPress() { if (ie && ie_version >= 9) this.hasSelection = null this.fastPoll() } onContextMenu(e) { let input = this, cm = input.cm, display = cm.display, te = input.textarea if (input.contextMenuPending) input.contextMenuPending() let pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop if (!pos || presto) return // Opera is difficult. // Reset the current text selection only if the click is done outside of the selection // and 'resetSelectionOnContextMenu' option is true. let reset = cm.options.resetSelectionOnContextMenu if (reset && cm.doc.sel.contains(pos) == -1) operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll) let oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText let wrapperBox = input.wrapper.offsetParent.getBoundingClientRect() input.wrapper.style.cssText = "position: static" te.style.cssText = `position: absolute; width: 30px; height: 30px; top: ${e.clientY - wrapperBox.top - 5}px; left: ${e.clientX - wrapperBox.left - 5}px; z-index: 1000; background: ${ie ? "rgba(255, 255, 255, .05)" : "transparent"}; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);` let oldScrollY if (webkit) oldScrollY = window.scrollY // Work around Chrome issue (#2712) display.input.focus() if (webkit) window.scrollTo(null, oldScrollY) display.input.reset() // Adds "Select all" to context menu in FF if (!cm.somethingSelected()) te.value = input.prevInput = " " input.contextMenuPending = rehide display.selForContextMenu = cm.doc.sel clearTimeout(display.detectingSelectAll) // Select-all will be greyed out if there's nothing to select, so // this adds a zero-width space so that we can later check whether // it got selected. function prepareSelectAllHack() { if (te.selectionStart != null) { let selected = cm.somethingSelected() let extval = "\u200b" + (selected ? te.value : "") te.value = "\u21da" // Used to catch context-menu undo te.value = extval input.prevInput = selected ? "" : "\u200b" te.selectionStart = 1; te.selectionEnd = extval.length // Re-set this, in case some other handler touched the // selection in the meantime. display.selForContextMenu = cm.doc.sel } } function rehide() { if (input.contextMenuPending != rehide) return input.contextMenuPending = false input.wrapper.style.cssText = oldWrapperCSS te.style.cssText = oldCSS if (ie && ie_version < 9) display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos) // Try to detect the user choosing select-all if (te.selectionStart != null) { if (!ie || (ie && ie_version < 9)) prepareSelectAllHack() let i = 0, poll = () => { if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 && te.selectionEnd > 0 && input.prevInput == "\u200b") { operation(cm, selectAll)(cm) } else if (i++ < 10) { display.detectingSelectAll = setTimeout(poll, 500) } else { display.selForContextMenu = null display.input.reset() } } display.detectingSelectAll = setTimeout(poll, 200) } } if (ie && ie_version >= 9) prepareSelectAllHack() if (captureRightClick) { e_stop(e) let mouseup = () => { off(window, "mouseup", mouseup) setTimeout(rehide, 20) } on(window, "mouseup", mouseup) } else { setTimeout(rehide, 50) } } readOnlyChanged(val) { if (!val) this.reset() this.textarea.disabled = val == "nocursor" this.textarea.readOnly = !!val } setUneditable() {} } TextareaInput.prototype.needsContentAttribute = false
Save
cmd:
run