Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Commit

Permalink
additional fixes for getFocusedEditor() for issue #1257
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonsanjose committed Oct 18, 2012
1 parent 772fec1 commit d20372c
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 76 deletions.
129 changes: 74 additions & 55 deletions src/editor/EditorManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@
*
* This module dispatches the following events:
* - focusedEditorChange -- Fires after the focused editor (full or inline)
* changes and size/visibility are complete.
* changes and size/visibility are complete. The
* 2nd arg is the newly focused editor or null if
* no editor has focus. The 3rd arg is the editor
* the previously focused editor or null if no
* editor had focus.
*/
define(function (require, exports, module) {
"use strict";
Expand Down Expand Up @@ -360,10 +364,70 @@ define(function (require, exports, module) {
resizeEditor(true);
}

/**
* Returns the currently focused inline widget.
* @returns {?{widget:!InlineTextEditor, editor:!Editor}}
*/
function getFocusedInlineWidget() {
var result = null;

if (_currentEditor) {
_currentEditor.getInlineWidgets().forEach(function (widget) {
if (widget instanceof InlineTextEditor) {
widget.editors.forEach(function (editor) {
if (editor.hasFocus()) {
result = { widget: widget, editor: editor };
}
});
}
});
}

return result;
}

function _getFocusedInlineEditor() {
var focusedInline = getFocusedInlineWidget();
if (focusedInline) {
return focusedInline.editor;
}

return null;
}

/**
* Returns the currently focused editor instance (full-sized OR inline editor).
* @returns {Editor}
*/
function getFocusedEditor() {
if (_currentEditor) {

// See if any inlines have focus
var focusedInline = _getFocusedInlineEditor();
if (focusedInline) {
return focusedInline;
}

// otherwise, see if full-sized editor has focus
if (_currentEditor.hasFocus()) {
return _currentEditor;
}
}

return null;
}

/**
* @private
*/
function _doFocusedEditorChanged(current, previous) {
if (current && !current.hasFocus()) {
current.focus();
return;
}

previous = previous || getFocusedEditor();

// Skip if the new editor is already the focused editor.
// This may happen if the window loses then regains focus.
if (previous === current) {
Expand Down Expand Up @@ -405,12 +469,14 @@ define(function (require, exports, module) {
* @param {!Document} document
*/
function _showEditor(document) {
// Save previous document to destroy after showing the new document
var previousDocument = _currentEditorsDocument;

// Hide whatever was visible before
if (!_currentEditor) {
$("#not-editor").css("display", "none");
} else {
_currentEditor.setVisible(false);
_destroyEditorIfUnneeded(_currentEditorsDocument);
}

// Ensure a main editor exists for this document to show in the UI
Expand All @@ -419,7 +485,13 @@ define(function (require, exports, module) {
_createFullEditorForDocument(document);
}

// show the new editor first before destroying the previous editor
_doShow(document);

// destroy old editor
if (previousDocument) {
_destroyEditorIfUnneeded(previousDocument);
}
}


Expand Down Expand Up @@ -505,59 +577,6 @@ define(function (require, exports, module) {

resizeEditor(); // if no files open at startup, we won't get called back later to resize the "no-editor" placeholder
}

/**
* Returns the currently focused inline widget.
* @returns {?{widget:!InlineTextEditor, editor:!Editor}}
*/
function getFocusedInlineWidget() {
var result = null;

if (_currentEditor) {
_currentEditor.getInlineWidgets().forEach(function (widget) {
if (widget instanceof InlineTextEditor) {
widget.editors.forEach(function (editor) {
if (editor.hasFocus()) {
result = { widget: widget, editor: editor };
}
});
}
});
}

return result;
}

function _getFocusedInlineEditor() {
var focusedInline = getFocusedInlineWidget();
if (focusedInline) {
return focusedInline.editor;
}

return null;
}

/**
* Returns the currently focused editor instance (full-sized OR inline editor).
* @returns {Editor}
*/
function getFocusedEditor() {
if (_currentEditor) {

// See if any inlines have focus
var focusedInline = _getFocusedInlineEditor();
if (focusedInline) {
return focusedInline;
}

// otherwise, see if full-sized editor has focus
if (_currentEditor.hasFocus()) {
return _currentEditor;
}
}

return null;
}

/**
* Toggle Quick Edit command handler
Expand Down
3 changes: 2 additions & 1 deletion src/editor/InlineTextEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ define(function (require, exports, module) {
}
InlineTextEditor.prototype = new InlineWidget();
InlineTextEditor.prototype.constructor = InlineTextEditor;
InlineTextEditor.prototype.parentClass = InlineWidget.prototype;

InlineTextEditor.prototype.editors = null;

Expand Down Expand Up @@ -170,6 +169,8 @@ define(function (require, exports, module) {
* editor is constructed and added to the DOM
*/
InlineTextEditor.prototype.onAdded = function () {
InlineWidget.prototype.onAdded.call(this); // super.onAdded()

this.editors.forEach(function (editor) {
editor.refresh();
});
Expand Down
3 changes: 2 additions & 1 deletion src/editor/InlineWidget.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ define(function (require, exports, module) {
e.stopImmediatePropagation();
}
});
this._added = false;
}
InlineWidget.prototype.htmlContent = null;
InlineWidget.prototype.$htmlContent = null;
Expand Down Expand Up @@ -84,7 +85,7 @@ define(function (require, exports, module) {
* focus or measuring content, which require htmlContent to be in the DOM tree.
*/
InlineWidget.prototype.onAdded = function () {
// do nothing - base implementation
this._added = true;
};

/**
Expand Down
57 changes: 38 additions & 19 deletions src/editor/MultiRangeInlineEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ define(function (require, exports, module) {
}
MultiRangeInlineEditor.prototype = new InlineTextEditor();
MultiRangeInlineEditor.prototype.constructor = MultiRangeInlineEditor;
MultiRangeInlineEditor.prototype.parentClass = InlineTextEditor.prototype;

MultiRangeInlineEditor.prototype.$editorsDiv = null;
MultiRangeInlineEditor.prototype.$relatedContainer = null;
Expand All @@ -113,7 +112,7 @@ define(function (require, exports, module) {
*
*/
MultiRangeInlineEditor.prototype.load = function (hostEditor) {
this.parentClass.load.call(this, hostEditor);
InlineTextEditor.prototype.load.call(this, hostEditor);

// Container to hold all editors
var self = this;
Expand Down Expand Up @@ -218,32 +217,50 @@ define(function (require, exports, module) {

this._ranges[this._selectedRangeIndex].$listItem.toggleClass("selected", true);

// Remove previous editors
$(this.editors[0]).off("change", this._updateRelatedContainer);

this.editors.forEach(function (editor) {
editor.destroy(); //release ref on Document
});
// Save old editors to destroy after new editor gets focus
var previousEditor = this.editors[0];

// Remove previous editor's event handlers
$(previousEditor).off(".MultiRangeInlineEditor");

this.editors = [];
this.$editorsDiv.children().remove();
var $preivousEditorDOM = this.$editorsDiv.children();

// Add new editor
var range = this._getSelectedRange();
this.createInlineEditorFromText(range.textRange.document, range.textRange.startLine, range.textRange.endLine, this.$editorsDiv.get(0));
this.editors[0].focus();

// Keep both previous editors[0] and current editors[1] temporarily
// until focusedEditorChange is fired. editors[1] won't exist when
// the first inline editor is created.
var currentInlineEditor = this.editors[1] || this.editors[0],
$currentInlineEditor = $(currentInlineEditor);

// Do not set focus during initialization. InlineWidget is not added to Editor yet.
if (this._added) {
// Set focus to new inline editor. Fires focusedEditorChange event
currentInlineEditor.focus();
}

// Destroy the previous editor after focusedEditorChange event is fired
if (previousEditor) {
previousEditor.destroy();

// Remove the previous editor
this.editors.shift();
$preivousEditorDOM.remove();
}

// Changes in size to the inline editor should update the relatedContainer
// Note: normally it's not kosher to listen to changes on a specific editor,
// but in this case we're specifically concerned with changes in the given
// editor, not general document changes.
$(this.editors[0]).on("change", this._handleChange);
$currentInlineEditor.on("change.MultiRangeInlineEditor", this._handleChange);

// Cursor activity in the inline editor may cause us to horizontally scroll.
$(this.editors[0]).on("cursorActivity", this._ensureCursorVisible);
$currentInlineEditor.on("cursorActivity.MultiRangeInlineEditor", this._ensureCursorVisible);

currentInlineEditor.refresh();

this.editors[0].refresh();
// ensureVisibility is set to false because we don't want to scroll the main editor when the user selects a view
this.sizeInlineWidgetToContents(true, false);
this._updateRelatedContainer();
Expand Down Expand Up @@ -318,12 +335,14 @@ define(function (require, exports, module) {
* Called any time inline is closed, whether manually (via closeThisInline()) or automatically
*/
MultiRangeInlineEditor.prototype.onClosed = function () {
this.parentClass.onClosed.call(this); // super.onClosed()
InlineTextEditor.prototype.onClosed.call(this); // super.onClosed()

// remove resize handlers for relatedContainer
$(this.hostEditor).off("change", this._updateRelatedContainer);
$(this.editors[0]).off("change", this._handleChange);
$(this.editors[0]).off("cursorActivity", this._ensureCursorVisible);

// remove event handlers
$(this.editors[0]).off(".MultiRangeInlineEditor");

$(this).off("offsetTopChanged", this._updateRelatedContainer);
$(window).off("resize", this._updateRelatedContainer);

Expand Down Expand Up @@ -474,7 +493,7 @@ define(function (require, exports, module) {
// Ignore when the editor's content got lost due to a deleted file
if (cause && cause.type === "deleted") { return; }
// Else yield to the parent's implementation
return this.parentClass._onLostContent.apply(this, arguments);
return InlineTextEditor.prototype._onLostContent.apply(this, arguments);
};

/**
Expand Down Expand Up @@ -513,7 +532,7 @@ define(function (require, exports, module) {
*/
MultiRangeInlineEditor.prototype.sizeInlineWidgetToContents = function (force, ensureVisibility) {
// Size the code mirror editors height to the editor content
this.parentClass.sizeInlineWidgetToContents.call(this, force);
InlineTextEditor.prototype.sizeInlineWidgetToContents.call(this, force);
// Size the widget height to the max between the editor content and the related ranges list
var widgetHeight = Math.max(this.$relatedContainer.find(".related").height(), this.$editorsDiv.height());
this.hostEditor.setInlineWidgetHeight(this, widgetHeight, ensureVisibility);
Expand Down

0 comments on commit d20372c

Please sign in to comment.