Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
8a283d4
add placeholder button to css inline editor
redmunds Oct 10, 2013
aaac429
Add addNewRuleToDocument() function
Oct 11, 2013
9c1c60f
Add addAndSelectRange() function to MultiRangeInlineEditor
Oct 11, 2013
8e66aa7
Add _addRule() to CSSInlineEditor
Oct 11, 2013
3f580cd
Fix require of Editor
Oct 11, 2013
c89ed3c
collect list of stylesheets; set enabled state of New Rule button
redmunds Oct 11, 2013
af1ea12
fix merge conflict
redmunds Oct 11, 2013
b61fa58
Start of work to make inline editor show message when there are no ru…
Oct 11, 2013
b9dd8b8
implement dropdown; hook up _addRule()
redmunds Oct 12, 2013
21fc0bd
fix conflicts
redmunds Oct 12, 2013
90c2f55
Merge branch 'master' into css-quick-edit-new-selector
Oct 12, 2013
e0c6789
don't pass unused params; currently getting data via closure
redmunds Oct 12, 2013
a719c78
Add header inside messages div. Fix stupid bug. Clean up creation of …
Oct 12, 2013
a3a7197
Merge branch 'css-quick-edit-new-selector' of https://github.com/adob…
Oct 12, 2013
6e632cf
event cleanup
redmunds Oct 14, 2013
39fe9ed
Make header persistent in InlineTextEditor:
Oct 15, 2013
81c3bee
refactor event ahndling into separate object
redmunds Oct 15, 2013
721c5e1
Merge branch 'css-quick-edit-new-selector' of https://github.com/adob…
redmunds Oct 15, 2013
8dfbf0f
Fix performance issue when switching between ranges in inline editor
Oct 15, 2013
54909b0
Merge branch 'css-quick-edit-new-selector' of https://github.com/adob…
Oct 15, 2013
fba79f4
Show appropriate message for no rules vs. no stylesheets in project
Oct 15, 2013
dfbc99f
Merge branch 'master' of https://github.com/adobe/brackets into css-q…
larz0 Oct 15, 2013
a8ed43f
Merge branch 'css-quick-edit-new-selector' of https://github.com/adob…
larz0 Oct 15, 2013
fdcd299
Styling first pass.
larz0 Oct 15, 2013
1d730b5
Message tweaks.
larz0 Oct 15, 2013
b564fef
Fix CM submodule
Oct 16, 2013
4bbc37d
Made filename less muted for a better visual hierarchy.
larz0 Oct 16, 2013
340ae12
Fix CM SHA again
Oct 16, 2013
cfc8f2a
beef up comments; restructure close/cleanup methods
redmunds Oct 16, 2013
6e3f12d
code cleanup; make button toggle dropdown
redmunds Oct 16, 2013
9a6423d
remove :hover from menu
redmunds Oct 17, 2013
1d5ee47
Fix broken JSQuickEdit unit test and make QuickView work again in inl…
Oct 17, 2013
c64412b
Move performance tweak into EditorManager.createInlineEditorForDocument
Oct 17, 2013
74ed9b8
more code cleanup from code review
redmunds Oct 17, 2013
167e419
Code review cleanups
Oct 17, 2013
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
177 changes: 165 additions & 12 deletions src/editor/CSSInlineEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,25 @@


/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, $, CodeMirror, window */
/*global define, $, CodeMirror, window, Mustache */

define(function (require, exports, module) {
"use strict";

// Load dependent modules
var CSSUtils = require("language/CSSUtils"),
DocumentManager = require("document/DocumentManager"),
DropdownEventHandler = require("utils/DropdownEventHandler").DropdownEventHandler,
EditorManager = require("editor/EditorManager"),
Editor = require("editor/Editor").Editor,
FileIndexManager = require("project/FileIndexManager"),
HTMLUtils = require("language/HTMLUtils"),
MultiRangeInlineEditor = require("editor/MultiRangeInlineEditor").MultiRangeInlineEditor;
Menus = require("command/Menus"),
MultiRangeInlineEditor = require("editor/MultiRangeInlineEditor").MultiRangeInlineEditor,
PopUpManager = require("widgets/PopUpManager"),
Strings = require("strings");

var StylesheetsMenuTemplate = require("text!htmlContent/stylesheets-menu.html");

/**
* Given a position in an HTML editor, returns the relevant selector for the attribute/tag
Expand Down Expand Up @@ -78,6 +87,33 @@ define(function (require, exports, module) {
return selectorName;
}

/**
* @private
* Create the list of stylesheets in the dropdown menu.
* @return {string} The html content
*/
function _renderList(cssFileInfos) {
var templateVars = {
styleSheetList : cssFileInfos
};

return Mustache.render(StylesheetsMenuTemplate, templateVars);
}

/**
* @private
* Add a new rule for the given selector to the given document, then add the rule to the
* given inline editor.
* @param {string} selectorName The selector to create a rule for.
* @param {MultiRangeInlineEditor} inlineEditor The inline editor to display the new rule in.
* @param {Document} styleDoc The document the rule should be inserted in.
*/
function _addRule(selectorName, inlineEditor, styleDoc) {
var newRuleInfo = CSSUtils.addRuleToDocument(styleDoc, selectorName, Editor.getUseTabChar(), Editor.getSpaceUnits());
inlineEditor.addAndSelectRange(selectorName, styleDoc, newRuleInfo.range.from.line, newRuleInfo.range.to.line);
inlineEditor.editor.setCursorPos(newRuleInfo.pos.line, newRuleInfo.pos.ch);
}

/**
* This function is registered with EditManager as an inline editor provider. It creates a CSSInlineEditor
* when cursor is on an HTML tag name, class attribute, or id attribute, find associated
Expand All @@ -89,6 +125,7 @@ define(function (require, exports, module) {
* or null if we're not going to provide anything.
*/
function htmlToCSSProvider(hostEditor, pos) {

// Only provide a CSS editor when cursor is in HTML content
if (hostEditor.getLanguageForSelection().getId() !== "html") {
return null;
Expand All @@ -107,19 +144,135 @@ define(function (require, exports, module) {
return null;
}

var result = new $.Deferred();
var result = new $.Deferred(),
cssInlineEditor,
cssFileInfos = [],
$newRuleButton,
$dropdown,
$dropdownItem,
dropdownEventHandler;

/**
* @private
* Close the dropdown.
*/
function _closeDropdown() {
// Since we passed "true" for autoRemove to addPopUp(), this will
// automatically remove the dropdown from the DOM. Also, PopUpManager
// will call _cleanupDropdown().
if ($dropdown) {
PopUpManager.removePopUp($dropdown);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This feels a bit leaky to me. The addPopUp call was made in DropdownEventHandler. It seems to me that perhaps DropdownEventHandler. This is the only call to PopUpManager in this file, which leads me to think there should really be a method on the DropdownEventHandler to do this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Fixed. I introduced a DropdownEventHandler.close() method.

}
}

/**
* @private
* Remove the various event handlers that close the dropdown. This is called by the
* PopUpManager when the dropdown is closed.
*/
function _cleanupDropdown() {
$("html").off("click", _closeDropdown);
dropdownEventHandler = null;
$dropdown = null;

EditorManager.focusEditor();
}

function _onSelect($link) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: the other functions here have jsdoc comments. I'm not actually very particular about jsdoc comments for simple interior functions like this, but it would be more consistent to have a comment since the others do.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@redmunds - do you want to add comments for those functions? If not I can take a stab at it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'll add jsdoc comments

var path = $link.data("path");

if (path) {
DocumentManager.getDocumentForPath(path).done(function (styleDoc) {
_addRule(selectorName, cssInlineEditor, styleDoc);
});
}
}

/**
* @private
* Show or hide the stylesheets dropdown.
*/
function _showDropdown() {
// If the dropdown is already visible, just return (so the root click handler on html
// will close it).
if ($dropdown) {
return;
}

Menus.closeAll();

$dropdown = $(_renderList(cssFileInfos));

var toggleOffset = $newRuleButton.offset();
$dropdown
.css({
left: toggleOffset.left,
top: toggleOffset.top + $newRuleButton.outerHeight()
})
.appendTo($("body"));

$("html").on("click", _closeDropdown);

dropdownEventHandler = new DropdownEventHandler($dropdown, _onSelect, _cleanupDropdown);
dropdownEventHandler.open();

$dropdown.focus();
}

/**
* @private
* Display list of stylesheets in project, then create a new rule in the given stylesheet and
* add it to the given inline editor.
* @param {string} selectorName The selector to create a rule for.
* @param {MultiRangeInlineEditor} inlineEditor The inline editor to display the new rule in.
*/
function _handleNewRule() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This appears to be left over from some kind of refactoring. The doc comments are out of date, and this function just calls _showDropdown. Perhaps this function should be eliminated entirely?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Fixed. Also made button toggle dropdown.

_showDropdown();
}

/**
* @private
* Checks to see if there are any stylesheets in the project, and returns the appropriate
* "no rules"/"no stylesheets" message accordingly.
* @return {$.Promise} a promise that is resolved with the message to show. Never rejected.
*/
function _getNoRulesMsg() {
var result = new $.Deferred();
FileIndexManager.getFileInfoList("css").done(function (fileInfos) {
result.resolve(fileInfos.length ? Strings.CSS_QUICK_EDIT_NO_MATCHES : Strings.CSS_QUICK_EDIT_NO_STYLESHEETS);
});
return result;
}

CSSUtils.findMatchingRules(selectorName, hostEditor.document)
.done(function (rules) {
if (rules && rules.length > 0) {
var cssInlineEditor = new MultiRangeInlineEditor(rules);
cssInlineEditor.load(hostEditor);

result.resolve(cssInlineEditor);
} else {
// No matching rules were found.
result.reject();
}
cssInlineEditor = new MultiRangeInlineEditor(rules || [], _getNoRulesMsg);
cssInlineEditor.load(hostEditor);

var $header = $(".inline-editor-header", cssInlineEditor.$htmlContent);
$newRuleButton = $("<button class='stylesheet-button btn btn-mini disabled'/>")
.text(Strings.BUTTON_NEW_RULE)
.on("click", function (e) {
if (!$newRuleButton.hasClass("disabled")) {
_handleNewRule();
}
e.stopPropagation();
});
$header.append($newRuleButton);

result.resolve(cssInlineEditor);

// Now that dialog has been built, collect list of stylesheets
FileIndexManager.getFileInfoList("css")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: it seems like the calls to getFileInfoList should be consolidated into one, especially given that the results are being saved by this one.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

My original thinking was that when we go to show the "no rules" message, if the user creates a stylesheet in between the time the inline editor was opened and the time we show the message, we'd want to know that and show the other message. However, we'd have to do other work to detect that and refresh the message/re-enable the button anyhow (which we're not doing currently). I think we should do that, but it's a separate task.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ahh, I see. Yes, that can be a separate task.

.done(function (fileInfos) {
cssFileInfos = fileInfos;

// "New Rule" button is disabled by default and gets enabled
// here if there are any stylesheets in project
if (cssFileInfos.length > 0) {
$newRuleButton.removeClass("disabled");
}
});
})
.fail(function () {
console.log("Error in findMatchingRules()");
Expand Down
4 changes: 2 additions & 2 deletions src/editor/EditorManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,8 @@ define(function (require, exports, module) {

if (hostEditor) {
hostEditor.getInlineWidgets().forEach(function (widget) {
if (widget instanceof InlineTextEditor) {
inlineEditors = inlineEditors.concat(widget.editors);
if (widget instanceof InlineTextEditor && widget.editor) {
inlineEditors.push(widget.editor);
}
});
}
Expand Down
Loading