Modules (180)

InlineTextEditor

Description

Dependencies

Functions

Private

_dirtyFlagChangeHandler

Respond to dirty flag change event. If the dirty flag is associated with an inline editor, show (or hide) the dirty indicator.

    function _dirtyFlagChangeHandler(event, doc) {
        var $dirtyIndicators = $(".inline-text-editor .dirty-indicator"),
            $indicator;

        $dirtyIndicators.each(function (index, indicator) {
            $indicator = $(this);
            if ($indicator.data("fullPath") === doc.file.fullPath) {
                _showDirtyIndicator($indicator, doc.isDirty);
            }
        });
    }
Private

_showDirtyIndicator

Shows or hides the dirty indicator

    function _showDirtyIndicator($indicatorDiv, isDirty) {
        // Show or hide the dirty indicator by adjusting
        // the width of the div.
        $indicatorDiv.css("width", isDirty ? 16 : 0);
    }
Private

_syncGutterWidths

Given a host editor and its inline editors, find the widest gutter and make all the others match

hostEditor non-nullable Editor
Host editor containing all the inline editors to sync
    function _syncGutterWidths(hostEditor) {
        var allHostedEditors = EditorManager.getInlineEditors(hostEditor);

        // add the host itself to the list too
        allHostedEditors.push(hostEditor);

        var maxWidth = 0;
        allHostedEditors.forEach(function (editor) {
            var $gutter = $(editor._codeMirror.getGutterElement()).find(".CodeMirror-linenumbers");
            $gutter.css("min-width", "");
            var curWidth = $gutter.width();
            if (curWidth > maxWidth) {
                maxWidth = curWidth;
            }
        });

        if (allHostedEditors.length === 1) {
            //There's only the host, just refresh the gutter
            allHostedEditors[0]._codeMirror.setOption("gutters", allHostedEditors[0]._codeMirror.getOption("gutters"));
            return;
        }

        maxWidth = maxWidth + "px";
        allHostedEditors.forEach(function (editor) {
            $(editor._codeMirror.getGutterElement()).find(".CodeMirror-linenumbers").css("min-width", maxWidth);

            // Force CodeMirror to refresh the gutter
            editor._codeMirror.setOption("gutters", editor._codeMirror.getOption("gutters"));
        });
    }

Classes

Constructor

InlineTextEditor (extends InlineWidget)

    function InlineTextEditor() {
        InlineWidget.call(this);

        this.editor = null;

        // We need to set this as a capture handler so CodeMirror doesn't handle Esc before we see it.
        this.handleKeyDown = this.handleKeyDown.bind(this);
        this.htmlContent.addEventListener("keydown", this.handleKeyDown, true);
    }
    InlineTextEditor.prototype = Object.create(InlineWidget.prototype);
    InlineTextEditor.prototype.constructor = InlineTextEditor;
    InlineTextEditor.prototype.parentClass = InlineWidget.prototype;

    InlineTextEditor.prototype.$wrapper = null;

Properties

editor

Type
Editor
    InlineTextEditor.prototype.editor = null;
    InlineTextEditor.prototype.$editorHolder = null;
    InlineTextEditor.prototype.$header = null;
    InlineTextEditor.prototype.$filename = null;

Methods

Private

_onLostContent

If Document's file is deleted, or Editor loses sync with Document, just close

    InlineTextEditor.prototype._onLostContent = function () {
        // Note: this closes the entire inline widget if any one Editor loses sync. This seems
        // better than leaving it open but suddenly removing one rule from the result list.
        this.close();
    };


    // Consolidate all dirty document updates
    // Due to circular dependencies, not safe to call on() directly
    EventDispatcher.on_duringInit(DocumentManager, "dirtyFlagChange", _dirtyFlagChangeHandler);

    exports.InlineTextEditor = InlineTextEditor;

});
Private

_updateLineRange

Updates start line display.

editor Editor
    InlineTextEditor.prototype._updateLineRange = function (editor) {
        this._startLine = editor.getFirstVisibleLine();
        this._endLine = editor.getLastVisibleLine();
        this._lineCount = this._endLine - this._startLine;

        this.$lineNumber.text(this._startLine + 1);
    };

getFocusedEditor

Returns: ?Editor
If an Editor within this inline editor has focus, returns it. Otherwise returns null.
    InlineTextEditor.prototype.getFocusedEditor = function () {
        if (this.editor && this.editor.hasFocus()) {
            return this.editor;
        }
        return null;
    };
Private

handleKeyDown

    InlineTextEditor.prototype.handleKeyDown = function (e) {
        if (e.keyCode === KeyEvent.DOM_VK_ESCAPE && this.editor && this.editor.getSelections().length > 1) {
            CodeMirror.commands.singleSelection(this.editor._codeMirror);
            e.stopImmediatePropagation();
        }
    };

load

hostEditor Editor
    InlineTextEditor.prototype.load = function (hostEditor) {
        InlineTextEditor.prototype.parentClass.load.apply(this, arguments);

        // We don't create the actual editor here--that will happen the first time
        // setInlineContent() is called.
        this.$wrapper = $("<div/>").addClass("inline-text-editor").appendTo(this.$htmlContent);
        this.$header = $("<div/>").addClass("inline-editor-header").appendTo(this.$wrapper);
        this.$filename = $("<a/>").addClass("filename").appendTo(this.$header);
        this.$editorHolder = $("<div/>").addClass("inline-editor-holder").appendTo(this.$wrapper);
    };

onAdded

Some tasks have to wait until we've been parented into the outer editor

the string
inline ID that is generated by CodeMirror after the widget that holds the inline editor is constructed and added to the DOM
    InlineTextEditor.prototype.onAdded = function () {
        var self = this;

        InlineTextEditor.prototype.parentClass.onAdded.apply(this, arguments);

        if (this.editor) {
            this.editor.refresh();
        }

        // Update display of inline editors when the hostEditor signals a redraw
        CodeMirror.on(this.info, "redraw", function () {
            // At the point where we get the redraw, CodeMirror might not yet have actually
            // re-added the widget to the DOM. This is filed as https://github.com/codemirror/CodeMirror/issues/1226.
            // For now, we can work around it by doing the refresh on a setTimeout().
            window.setTimeout(function () {
                if (self.editor) {
                    self.editor.refresh();
                }
            }, 0);
        });

        _syncGutterWidths(this.hostEditor);

        if (this.editor) {
            this.editor.focus();
        }
    };

onClosed

Called any time inline was closed, whether manually (via close()) or automatically

    InlineTextEditor.prototype.onClosed = function () {
        InlineTextEditor.prototype.parentClass.onClosed.apply(this, arguments);

        _syncGutterWidths(this.hostEditor);

        // Destroy the inline editor.
        this.setInlineContent(null);
        this.htmlContent.removeEventListener("keydown", this.handleKeyDown, true);
    };

onParentShown

Called when the editor containing the inline is made visible.

    InlineTextEditor.prototype.onParentShown = function () {
        InlineTextEditor.prototype.parentClass.onParentShown.apply(this, arguments);

        // Refresh line number display and codemirror line number gutter
        if (this.editor) {
            this._updateLineRange(this.editor);
            this.editor.refresh();
        }

        // We need to call this explicitly whenever the host editor is reshown
        this.sizeInlineWidgetToContents();
    };

setInlineContent

Sets the document and range to show in the inline editor, or null to destroy the current editor and leave the content blank.

doc Document
The document to show, or null to show nothing
startLine number
The first line of text in `doc` to show in inline editor. Ignored if doc is null.
endLine number
The last line of text in `doc` to show in inline editor. Ignored if doc is null.
    InlineTextEditor.prototype.setInlineContent = function (doc, startLine, endLine) {
        var self = this;

        // Destroy the previous editor if we had one and clear out the filename info.
        if (this.editor) {
            this.editor.off(".InlineTextEditor");
            this.editor.destroy(); // remove from DOM and release ref on Document
            this.editor = null;
            this.$filename.off(".InlineTextEditor")
                .removeAttr("title");
            this.$filename.html("");
        }

        if (!doc) {
            return;
        }

        var range = {
            startLine: startLine,
            endLine: endLine
        };

        // dirty indicator, with file path stored on it
        var $dirtyIndicatorDiv = $("<div/>")
            .addClass("dirty-indicator")
            .html("&bull;")
            .width(0); // initialize indicator as hidden
        $dirtyIndicatorDiv.data("fullPath", doc.file.fullPath);

        this.$lineNumber = $("<span class='line-number'/>");

        // update contents of filename link
        this.$filename.append($dirtyIndicatorDiv)
            .append(doc.file.name + " : ")
            .append(this.$lineNumber)
            .attr("title", doc.file.fullPath);

        // clicking filename jumps to full editor view
        this.$filename.on("click.InlineTextEditor", function () {
            CommandManager.execute(Commands.FILE_OPEN, { fullPath: doc.file.fullPath })
                .done(function () {
                    EditorManager.getCurrentFullEditor().setCursorPos(startLine, 0, true);
                });
        });

        var inlineInfo = EditorManager.createInlineEditorForDocument(doc, range, this.$editorHolder.get(0));
        this.editor = inlineInfo.editor;

        // Init line number display
        this._updateLineRange(inlineInfo.editor);

        // Always update the widget height when an inline editor completes a
        // display update
        this.editor.on("update.InlineTextEditor", function (event, editor) {
            self.sizeInlineWidgetToContents();
        });

        // Size editor to content whenever text changes (via edits here or any
        // other view of the doc: Editor fires "change" any time its text
        // changes, regardless of origin)
        this.editor.on("change.InlineTextEditor", function (event, editor) {
            if (self.hostEditor.isFullyVisible()) {
                self.sizeInlineWidgetToContents();
                self._updateLineRange(editor);
            }
        });

        // If Document's file is deleted, or Editor loses sync with Document, delegate to this._onLostContent()
        this.editor.on("lostContent.InlineTextEditor", function () {
            self._onLostContent.apply(self, arguments);
        });

        // set dirty indicator state
        _showDirtyIndicator($dirtyIndicatorDiv, doc.isDirty);
    };

sizeInlineWidgetToContents

Update the inline editor's height when the number of lines change. The base implementation of this method does nothing.

    InlineTextEditor.prototype.sizeInlineWidgetToContents = function () {
        // brackets_codemirror_overrides.css adds height:auto to CodeMirror
        // Inline editors themselves do not need to be sized, but layouts like
        // the one used in CSSInlineEditor do need some manual layout.
    };