Bug 961431 - Autocomplete suggestions in split console are sliding down. r=robcee
--- a/browser/devtools/inspector/selector-search.js
+++ b/browser/devtools/inspector/selector-search.js
@@ -45,17 +45,16 @@ function SelectorSearch(aInspector, aCon
this._onHTMLSearch = this._onHTMLSearch.bind(this);
this._onSearchKeypress = this._onSearchKeypress.bind(this);
this._onListBoxKeypress = this._onListBoxKeypress.bind(this);
// Options for the AutocompletePopup.
let options = {
panelId: "inspector-searchbox-panel",
listBoxId: "searchbox-panel-listbox",
- fixedWidth: true,
autoSelect: true,
position: "before_start",
direction: "ltr",
onClick: this._onListBoxKeypress,
onKeypress: this._onListBoxKeypress,
};
this.searchPopup = new AutocompletePopup(this.panelDoc, options);
--- a/browser/devtools/markupview/markup-view.js
+++ b/browser/devtools/markupview/markup-view.js
@@ -71,17 +71,16 @@ function MarkupView(aInspector, aFrame,
try {
this.maxChildren = Services.prefs.getIntPref("devtools.markup.pagesize");
} catch(ex) {
this.maxChildren = DEFAULT_MAX_CHILDREN;
}
// Creating the popup to be used to show CSS suggestions.
let options = {
- fixedWidth: true,
autoSelect: true,
theme: "auto"
};
this.popup = new AutocompletePopup(this.doc.defaultView.parent.document, options);
this.undo = new UndoStack();
this.undo.installController(aControllerWindow);
--- a/browser/devtools/shared/autocomplete-popup.js
+++ b/browser/devtools/shared/autocomplete-popup.js
@@ -20,27 +20,25 @@ loader.lazyImporter(this, "gDevTools", "
* @param Object aOptions
* An object consiting any of the following options:
* - panelId {String} The id for the popup panel.
* - listBoxId {String} The id for the richlistbox inside the panel.
* - position {String} The position for the popup panel.
* - theme {String} String related to the theme of the popup.
* - autoSelect {Boolean} Boolean to allow the first entry of the popup
* panel to be automatically selected when the popup shows.
- * - fixedWidth {Boolean} Boolean to control dynamic width of the popup.
* - direction {String} The direction of the text in the panel. rtl or ltr
* - onSelect {String} The select event handler for the richlistbox
* - onClick {String} The click event handler for the richlistbox.
* - onKeypress {String} The keypress event handler for the richlistitems.
*/
function AutocompletePopup(aDocument, aOptions = {})
{
this._document = aDocument;
- this.fixedWidth = aOptions.fixedWidth || false;
this.autoSelect = aOptions.autoSelect || false;
this.position = aOptions.position || "after_start";
this.direction = aOptions.direction || "ltr";
this.onSelect = aOptions.onSelect;
this.onClick = aOptions.onClick;
this.onKeypress = aOptions.onKeypress;
@@ -70,17 +68,16 @@ function AutocompletePopup(aDocument, aO
let mainPopupSet = this._document.getElementById("mainPopupSet");
if (mainPopupSet) {
mainPopupSet.appendChild(this._panel);
}
else {
this._document.documentElement.appendChild(this._panel);
}
- this._list = null;
}
else {
this._list = this._panel.firstChild;
}
if (!this._list) {
this._list = this._document.createElementNS(XUL_NS, "richlistbox");
this._panel.appendChild(this._list);
@@ -132,24 +129,23 @@ AutocompletePopup.prototype = {
* Horizontal offset in pixels from the left of the node to the left
* of the popup.
* @param Number aYOffset
* Vertical offset in pixels from the top of the node to the starting
* of the popup.
*/
openPopup: function AP_openPopup(aAnchor, aXOffset = 0, aYOffset = 0)
{
+ this.__maxLabelLength = -1;
+ this._updateSize();
this._panel.openPopup(aAnchor, this.position, aXOffset, aYOffset);
if (this.autoSelect) {
this.selectFirstItem();
}
- if (!this.fixedWidth) {
- this._updateSize();
- }
},
/**
* Hide the autocomplete popup panel.
*/
hidePopup: function AP_hidePopup()
{
this._panel.hidePopup();
@@ -236,90 +232,95 @@ AutocompletePopup.prototype = {
this.clearItems();
aItems.forEach(this.appendItem, this);
// Make sure that the new content is properly fitted by the XUL richlistbox.
if (this.isOpen) {
if (this.autoSelect) {
this.selectFirstItem();
}
- if (!this.fixedWidth) {
- this._updateSize();
- }
+ this._updateSize();
}
},
/**
* Selects the first item of the richlistbox. Note that first item here is the
* item closes to the input element, which means that 0th index if position is
* below, and last index if position is above.
*/
selectFirstItem: function AP_selectFirstItem()
{
if (this.position.contains("before")) {
this.selectedIndex = this.itemCount - 1;
}
else {
this.selectedIndex = 0;
}
+ this._list.ensureIndexIsVisible(this._list.selectedIndex);
+ },
+
+ __maxLabelLength: -1,
+
+ get _maxLabelLength() {
+ if (this.__maxLabelLength != -1) {
+ return this.__maxLabelLength;
+ }
+
+ let max = 0;
+ for (let i = 0; i < this._list.childNodes.length; i++) {
+ let item = this._list.childNodes[i]._autocompleteItem;
+ let str = item.label;
+ if (item.count) {
+ str += (item.count + "");
+ }
+ max = Math.max(str.length, max);
+ }
+
+ this.__maxLabelLength = max;
+ return this.__maxLabelLength;
},
/**
* Update the panel size to fit the content.
*
* @private
*/
_updateSize: function AP__updateSize()
{
if (!this._panel) {
return;
}
- // Flush the layout so that we get the latest height.
- this._panel.boxObject.height;
- let height = {};
- this._list.scrollBoxObject.getScrolledSize({}, height);
- // Change the width of the popup only if the scrollbar is visible.
- if (height.value > this._panel.clientHeight) {
- this._list.width = this._panel.clientWidth + this._scrollbarWidth;
- }
- // Height change is required, otherwise the panel is drawn at an offset
- // the first time.
- this._list.height = this._list.clientHeight;
- // This brings the panel back at right position.
- this._list.top = 0;
- // Move the panel to -1,-1 to realign the popup with its anchor node when
- // decreasing the panel height.
- this._panel.moveTo(-1, -1);
- // Changing panel height might make the selected item out of view, so
- // bring it back to view.
+
+ this._list.style.width = (this._maxLabelLength + 3) +"ch";
this._list.ensureIndexIsVisible(this._list.selectedIndex);
},
/**
* Clear all the items from the autocomplete list.
*/
clearItems: function AP_clearItems()
{
// Reset the selectedIndex to -1 before clearing the list
this.selectedIndex = -1;
while (this._list.hasChildNodes()) {
this._list.removeChild(this._list.firstChild);
}
- if (!this.fixedWidth) {
- // Reset the panel and list dimensions. New dimensions are calculated when
- // a new set of items is added to the autocomplete popup.
- this._list.width = "";
- this._list.height = "";
- this._panel.width = "";
- this._panel.height = "";
- this._panel.top = "";
- this._panel.left = "";
- }
+ this.__maxLabelLength = -1;
+
+ // Reset the panel and list dimensions. New dimensions are calculated when
+ // a new set of items is added to the autocomplete popup.
+ this._list.width = "";
+ this._list.style.width = "";
+ this._list.height = "";
+ this._panel.width = "";
+ this._panel.height = "";
+ this._panel.top = "";
+ this._panel.left = "";
},
/**
* Getter for the index of the selected item.
*
* @type number
*/
get selectedIndex() {
@@ -492,48 +493,16 @@ AutocompletePopup.prototype = {
* Focuses the richlistbox.
*/
focus: function AP_focus()
{
this._list.focus();
},
/**
- * Determine the scrollbar width in the current document.
- *
- * @private
- */
- get _scrollbarWidth()
- {
- if (this.__scrollbarWidth !== null) {
- return this.__scrollbarWidth;
- }
-
- let doc = this._document;
- if (doc.defaultView.matchMedia("(-moz-overlay-scrollbars)").matches) {
- // This is for the Mac's floating scrollbar, which actually is drawn over
- // the content, thus taking no extra width.
- return (this.__scrollbarWidth = 0);
- }
-
- let hbox = doc.createElementNS(XUL_NS, "hbox");
- hbox.setAttribute("style", "height: 0%; overflow: hidden");
-
- let scrollbar = doc.createElementNS(XUL_NS, "scrollbar");
- scrollbar.setAttribute("orient", "vertical");
- hbox.appendChild(scrollbar);
- doc.documentElement.appendChild(hbox);
-
- this.__scrollbarWidth = scrollbar.clientWidth;
- doc.documentElement.removeChild(hbox);
-
- return this.__scrollbarWidth;
- },
-
- /**
* Manages theme switching for the popup based on the devtools.theme pref.
*
* @private
*
* @param String aEvent
* The name of the event. In this case, "pref-changed".
* @param Object aData
* An object passed by the emitter of the event. In this case, the
--- a/browser/devtools/styleinspector/rule-view.js
+++ b/browser/devtools/styleinspector/rule-view.js
@@ -1084,17 +1084,16 @@ function CssRuleView(aInspector, aDoc, a
this._handlePrefChange = this._handlePrefChange.bind(this);
gDevTools.on("pref-changed", this._handlePrefChange);
this._onSourcePrefChanged = this._onSourcePrefChanged.bind(this);
this._prefObserver = new PrefObserver("devtools.");
this._prefObserver.on(PREF_ORIG_SOURCES, this._onSourcePrefChanged);
let options = {
- fixedWidth: true,
autoSelect: true,
theme: "auto"
};
this.popup = new AutocompletePopup(aDoc.defaultView.parent.document, options);
// Create a tooltip for previewing things in the rule view (images for now)
this.previewTooltip = new Tooltip(this.inspector.panelDoc);
this.previewTooltip.startTogglingOnHover(this.element,