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

Initial Quick Docs implementation #3449

Merged
merged 7 commits into from
Apr 18, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/base-config/keyboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@
"navigate.toggleQuickEdit": [
"Ctrl-E"
],
"navigate.toggleQuickDocs": [
"Ctrl-K"
],
"navigate.previousMatch": [
{
"key": "Alt-Up",
Expand Down
1 change: 1 addition & 0 deletions src/command/Commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ define(function (require, exports, module) {
exports.NAVIGATE_GOTO_DEFINITION = "navigate.gotoDefinition";
exports.NAVIGATE_GOTO_LINE = "navigate.gotoLine";
exports.TOGGLE_QUICK_EDIT = "navigate.toggleQuickEdit";
exports.TOGGLE_QUICK_DOCS = "navigate.toggleQuickDocs";
exports.QUICK_EDIT_NEXT_MATCH = "navigate.nextMatch";
exports.QUICK_EDIT_PREV_MATCH = "navigate.previousMatch";

Expand Down
3 changes: 3 additions & 0 deletions src/command/DefaultMenus.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ define(function (require, exports, module) {
menu.addMenuItem(Commands.TOGGLE_QUICK_EDIT);
menu.addMenuItem(Commands.QUICK_EDIT_PREV_MATCH);
menu.addMenuItem(Commands.QUICK_EDIT_NEXT_MATCH);
menu.addMenuDivider();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally we ask extensions to add menus within the extension and not in DefaultMenus right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but this isn't an extension Command, is a new Quick Docs Command handled by the Editor Manager and the extension just adds a new Quick Docs provider that uses this command, just like Quick Edit works.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yes. Thanks for catching my mistake. :)

menu.addMenuItem(Commands.TOGGLE_QUICK_DOCS);

/*
* Help menu
Expand Down Expand Up @@ -197,6 +199,7 @@ define(function (require, exports, module) {

var editor_cmenu = Menus.registerContextMenu(Menus.ContextMenuIds.EDITOR_MENU);
editor_cmenu.addMenuItem(Commands.TOGGLE_QUICK_EDIT);
editor_cmenu.addMenuItem(Commands.TOGGLE_QUICK_DOCS);
editor_cmenu.addMenuItem(Commands.EDIT_SELECT_ALL);

var inline_editor_cmenu = Menus.registerContextMenu(Menus.ContextMenuIds.INLINE_EDITOR_MENU);
Expand Down
6 changes: 3 additions & 3 deletions src/editor/CSSInlineEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,14 @@ define(function (require, exports, module) {
}

// Only provide CSS editor if the selection is within a single line
var sel = hostEditor.getSelection(false);
var sel = hostEditor.getSelection();
if (sel.start.line !== sel.end.line) {
return null;
}

// Always use the selection start for determining selector name. The pos
// parameter is usually the selection end.
var selectorName = _getSelectorName(hostEditor, hostEditor.getSelection(false).start);
// parameter is usually the selection end.
var selectorName = _getSelectorName(hostEditor, sel.start);
if (selectorName === "") {
return null;
}
Expand Down
80 changes: 51 additions & 29 deletions src/editor/EditorManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ define(function (require, exports, module) {
*/
var _inlineEditProviders = [];

/**
* Registered inline documentation widget providers. See {@link #registerInlineDocsProvider()}.
* @type {Array.<function(...)>}
*/
var _inlineDocsProviders = [];

/**
* @private
* @param {?Editor} current
Expand Down Expand Up @@ -134,39 +140,41 @@ define(function (require, exports, module) {

/**
* @private
* Bound to Ctrl+E on outermost editors.
* @param {!Editor} editor the candidate host editor
* Finds an inline widget provider from the given list that can offer a widget for the current cursor
* position, and once the widget has been created inserts it into the editor.
* @param {!Editor} editor The host editor
* @param {!Array.<function(!Editor, !{line:Number, ch:Number}):?$.Promise>} providers
* @return {$.Promise} a promise that will be resolved when an InlineWidget
* is created or rejected when no inline editors are available.
* is created or rejected if no inline providers have offered one.
*/
function _openInlineWidget(editor) {
PerfUtils.markStart(PerfUtils.INLINE_EDITOR_OPEN);
function _openInlineWidget(editor, providers) {
PerfUtils.markStart(PerfUtils.INLINE_WIDGET_OPEN);

// Run through inline-editor providers until one responds
var pos = editor.getCursorPos(),
inlinePromise,
i,
result = new $.Deferred();

for (i = 0; i < _inlineEditProviders.length && !inlinePromise; i++) {
var provider = _inlineEditProviders[i];
for (i = 0; i < providers.length && !inlinePromise; i++) {
var provider = providers[i];
inlinePromise = provider(editor, pos);
}

// If one of them will provide a widget, show it inline once ready
if (inlinePromise) {
inlinePromise.done(function (inlineWidget) {
editor.addInlineWidget(pos, inlineWidget);
PerfUtils.addMeasurement(PerfUtils.INLINE_EDITOR_OPEN);
PerfUtils.addMeasurement(PerfUtils.INLINE_WIDGET_OPEN);
result.resolve();
}).fail(function () {
// terminate timer that was started above
PerfUtils.finalizeMeasurement(PerfUtils.INLINE_EDITOR_OPEN);
PerfUtils.finalizeMeasurement(PerfUtils.INLINE_WIDGET_OPEN);
result.reject();
});
} else {
// terminate timer that was started above
PerfUtils.finalizeMeasurement(PerfUtils.INLINE_EDITOR_OPEN);
PerfUtils.finalizeMeasurement(PerfUtils.INLINE_WIDGET_OPEN);
result.reject();
}

Expand Down Expand Up @@ -197,21 +205,29 @@ define(function (require, exports, module) {
}

/**
* Registers a new inline provider. When _openInlineWidget() is called each registered inline
* widget is called and asked if it wants to provide an inline widget given the current cursor
* location and document.
* @param {function} provider
* Parameters:
* {!Editor} editor, {!{line:Number, ch:Number}} pos
*
* Returns:
* {$.Promise} a promise that will be resolved with an inlineWidget
* or null to indicate the provider doesn't create an editor in this case
* Registers a new inline editor provider. When Quick Edit is invoked each registered provider is
* asked if it wants to provide an inline editor given the current editor and cursor location.
*
* @param {function(!Editor, !{line:Number, ch:Number}):?$.Promise} provider
* The provider returns a promise that will be resolved with an InlineWidget, or returns null
* to indicate the provider doesn't want to respond to this case.
*/
function registerInlineEditProvider(provider) {
_inlineEditProviders.push(provider);
}

/**
* Registers a new inline docs provider. When Quick Docs is invoked each registered provider is
* asked if it wants to provide inline docs given the current editor and cursor location.
*
* @param {function(!Editor, !{line:Number, ch:Number}):?$.Promise} provider
* The provider returns a promise that will be resolved with an InlineWidget, or returns null
* to indicate the provider doesn't want to respond to this case.
*/
function registerInlineDocsProvider(provider) {
_inlineDocsProviders.push(provider);
}

/**
* @private
* Given a host editor, return a list of all Editors in all its open inline widgets. (Ignoring
Expand Down Expand Up @@ -649,28 +665,28 @@ define(function (require, exports, module) {


/**
* Toggle Quick Edit command handler
* @return {!Promise} A promise resolved with true if an inline editor
* is opened or false when closed. The promise is rejected if there
* is no current editor or an inline editor is not created.
* Closes any focused inline widget. Else, asynchronously asks providers to create one.
* @return {!Promise} A promise resolved with true if an inline widget is opened or false
* when closed. Rejected if there is neither an existing widget to close nor a provider
* willing to create a widget (or if no editor is open).
*/
function _toggleQuickEdit() {
function _toggleInlineWidget(providers) {
var result = new $.Deferred();

if (_currentEditor) {
var inlineWidget = getFocusedInlineWidget();

if (inlineWidget) {
// an inline widget's editor has focus, so close it
PerfUtils.markStart(PerfUtils.INLINE_EDITOR_CLOSE);
PerfUtils.markStart(PerfUtils.INLINE_WIDGET_CLOSE);
inlineWidget.close();
PerfUtils.addMeasurement(PerfUtils.INLINE_EDITOR_CLOSE);
PerfUtils.addMeasurement(PerfUtils.INLINE_WIDGET_CLOSE);

// return a resolved promise to CommandManager
result.resolve(false);
} else {
// main editor has focus, so create an inline editor
_openInlineWidget(_currentEditor).done(function () {
_openInlineWidget(_currentEditor, providers).done(function () {
result.resolve(true);
}).fail(function () {
result.reject();
Expand All @@ -685,7 +701,12 @@ define(function (require, exports, module) {
}

// Initialize: command handlers
CommandManager.register(Strings.CMD_TOGGLE_QUICK_EDIT, Commands.TOGGLE_QUICK_EDIT, _toggleQuickEdit);
CommandManager.register(Strings.CMD_TOGGLE_QUICK_EDIT, Commands.TOGGLE_QUICK_EDIT, function () {
return _toggleInlineWidget(_inlineEditProviders);
});
CommandManager.register(Strings.CMD_TOGGLE_QUICK_DOCS, Commands.TOGGLE_QUICK_DOCS, function () {
return _toggleInlineWidget(_inlineDocsProviders);
});

// Initialize: register listeners
$(DocumentManager).on("currentDocumentChange", _onCurrentDocumentChange);
Expand Down Expand Up @@ -718,6 +739,7 @@ define(function (require, exports, module) {
exports.getFocusedInlineWidget = getFocusedInlineWidget;
exports.resizeEditor = resizeEditor;
exports.registerInlineEditProvider = registerInlineEditProvider;
exports.registerInlineDocsProvider = registerInlineDocsProvider;
exports.getInlineEditors = getInlineEditors;
exports.closeInlineWidget = closeInlineWidget;
});
2 changes: 1 addition & 1 deletion src/editor/MultiRangeInlineEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ define(function (require, exports, module) {
MultiRangeInlineEditor.prototype.refresh = function () {
MultiRangeInlineEditor.prototype.parentClass.refresh.apply(this, arguments);
this.sizeInlineWidgetToContents(true);
this.editors.forEach(function (editor, j, arr) {
this.editors.forEach(function (editor) {
editor.refresh();
});
};
Expand Down
7 changes: 2 additions & 5 deletions src/extensions/default/InlineColorEditor/InlineColorEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ define(function (require, exports, module) {
doc.addRef();
$(doc).on("change", this._handleHostDocumentChange);

window.setTimeout(this._sizeEditorToContent.bind(this), 0);
this.hostEditor.setInlineWidgetHeight(this, this.colorEditor.getRootElement().outerHeight(), true);

this.colorEditor.focus();
};

Expand All @@ -216,10 +217,6 @@ define(function (require, exports, module) {
doc.releaseRef();
};

InlineColorEditor.prototype._sizeEditorToContent = function () {
this.hostEditor.setInlineWidgetHeight(this, this.colorEditor.getRootElement().outerHeight(), true);
};

/** Comparator to sort by which colors are used the most */
function _colorSort(a, b) {
if (a.count === b.count) {
Expand Down
2 changes: 0 additions & 2 deletions src/extensions/default/InlineColorEditor/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
*/

.color-editor {
-webkit-text-size-adjust: none;
font-size: 12px;
min-width: 450px;
height: 190px;
Expand Down Expand Up @@ -75,7 +74,6 @@
list-style: none;
}
.color-editor aside ul.swatches li {
-webkit-text-size-adjust: none;
height: 18px;
margin-bottom: 2px;
padding: 0 1px 1px 2px;
Expand Down
4 changes: 2 additions & 2 deletions src/extensions/default/JavaScriptQuickEdit/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,14 @@ define(function (require, exports, module) {
}

// Only provide JavaScript editor if the selection is within a single line
var sel = hostEditor.getSelection(false);
var sel = hostEditor.getSelection();
if (sel.start.line !== sel.end.line) {
return null;
}

// Always use the selection start for determining the function name. The pos
// parameter is usually the selection end.
var functionName = _getFunctionName(hostEditor, hostEditor.getSelection().start);
var functionName = _getFunctionName(hostEditor, sel.start);
if (!functionName) {
return null;
}
Expand Down
21 changes: 21 additions & 0 deletions src/extensions/default/WebPlatformDocs/InlineDocsViewer.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<div class="css-prop-defn">
<div class="css-prop-summary">
<h1>{{propName}}</h1>
<div>{{{summary}}}</div>
</div>
<div class="divider-holder">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually I'm not picky about non-semantic markup, but this jumped out at me. I assume this is tricky for some reason?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah... see the comment on the LESS rule for it. Essentially, to get the line centered in the gap between columns we need its offset to be some percentage plus half the fixed-size gap. I suppose we could use calc() for that but I've always been a little unsure how well non-IE browsers support that stuff...

Fwiw the .content-bottom div is another thing we only need for layout, since it's impossible to put a margin/padding gap directly between floated content and an immediate sibling (e.g. see http://stackoverflow.com/questions/4198269/in-css-margin-top-is-not-working-with-clear-both).

<div class="divider"></div>
</div>
<div class="css-prop-values quiet-scrollbars">
<div class="scroller" tabIndex="0"> <!-- tabIndex needed: otherwise click focuses CodeMirror scroller -->
<dl>
{{#propValues}}
<dt>{{value}}</dt>
<dd>{{{description}}}</dd>
{{/propValues}}
</dl>
</div>
</div>
<div class="content-bottom"></div>
<a class="more-info" href="{{url}}" title="{{url}}">{{DOCS_MORE_LINK}}</a>
</div>
Loading