зеркало из https://github.com/mozilla/gecko-dev.git
Bug 893965 - Autocomplete CSS properties in the rule view, r=mratcliffe, msucan
This commit is contained in:
Родитель
f4aa0cd2a0
Коммит
32c219f27c
|
@ -4,6 +4,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
// The XUL and XHTML namespace.
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
|
@ -11,6 +12,10 @@ const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
|||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gDevTools", function() {
|
||||
return Cu.import("resource:///modules/devtools/gDevTools.jsm", {}).gDevTools;
|
||||
});
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["AutocompletePopup"];
|
||||
|
||||
/**
|
||||
|
@ -49,6 +54,14 @@ function AutocompletePopup(aDocument, aOptions = {})
|
|||
|
||||
let id = aOptions.panelId || "devtools_autoCompletePopup";
|
||||
let theme = aOptions.theme || "dark";
|
||||
// If theme is auto, use the devtools.theme pref
|
||||
if (theme == "auto") {
|
||||
theme = Services.prefs.getCharPref("devtools.theme");
|
||||
this.autoThemeEnabled = true;
|
||||
// Setup theme change listener.
|
||||
this._handleThemeChange = this._handleThemeChange.bind(this);
|
||||
gDevTools.on("pref-changed", this._handleThemeChange);
|
||||
}
|
||||
// Reuse the existing popup elements.
|
||||
this._panel = this._document.getElementById(id);
|
||||
if (!this._panel) {
|
||||
|
@ -173,6 +186,10 @@ AutocompletePopup.prototype = {
|
|||
this._list.removeEventListener("keypress", this.onKeypress, false);
|
||||
}
|
||||
|
||||
if (this.autoThemeEnabled) {
|
||||
gDevTools.off("pref-changed", this._handleThemeChange);
|
||||
}
|
||||
|
||||
this._document = null;
|
||||
this._list = null;
|
||||
this._panel = null;
|
||||
|
@ -440,7 +457,7 @@ AutocompletePopup.prototype = {
|
|||
this.selectedIndex++;
|
||||
}
|
||||
else {
|
||||
this.selectedIndex = -1;
|
||||
this.selectedIndex = 0;
|
||||
}
|
||||
|
||||
return this.selectedItem;
|
||||
|
@ -454,7 +471,7 @@ AutocompletePopup.prototype = {
|
|||
*/
|
||||
selectPreviousItem: function AP_selectPreviousItem()
|
||||
{
|
||||
if (this.selectedIndex > -1) {
|
||||
if (this.selectedIndex > 0) {
|
||||
this.selectedIndex--;
|
||||
}
|
||||
else {
|
||||
|
@ -496,5 +513,28 @@ AutocompletePopup.prototype = {
|
|||
|
||||
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
|
||||
* object consists of three properties:
|
||||
* - pref {String} The name of the preference that was modified.
|
||||
* - newValue {Object} The new value of the preference.
|
||||
* - oldValue {Object} The old value of the preference.
|
||||
*/
|
||||
_handleThemeChange: function AP__handleThemeChange(aEvent, aData)
|
||||
{
|
||||
if (aData.pref == "devtools.theme") {
|
||||
this._panel.classList.toggle(aData.oldValue + "-theme", false);
|
||||
this._panel.classList.toggle(aData.newValue + "-theme", true);
|
||||
this._list.classList.toggle(aData.oldValue + "-theme", false);
|
||||
this._list.classList.toggle(aData.newValue + "-theme", true);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -24,9 +24,16 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const {Ci, Cu} = require("chrome");
|
||||
const {Ci, Cu, Cc} = require("chrome");
|
||||
|
||||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const CONTENT_TYPES = {
|
||||
PLAIN_TEXT: 0,
|
||||
CSS_VALUE: 1,
|
||||
CSS_MIXED: 2,
|
||||
CSS_PROPERTY: 3,
|
||||
};
|
||||
const MAX_POPUP_ENTRIES = 10;
|
||||
|
||||
const FOCUS_FORWARD = Ci.nsIFocusManager.MOVEFOCUS_FORWARD;
|
||||
const FOCUS_BACKWARD = Ci.nsIFocusManager.MOVEFOCUS_BACKWARD;
|
||||
|
@ -160,6 +167,8 @@ function InplaceEditor(aOptions, aEvent)
|
|||
this.initial = aOptions.initial ? aOptions.initial : this.elt.textContent;
|
||||
this.multiline = aOptions.multiline || false;
|
||||
this.stopOnReturn = !!aOptions.stopOnReturn;
|
||||
this.contentType = aOptions.contentType || CONTENT_TYPES.PLAIN_TEXT;
|
||||
this.popup = aOptions.popup;
|
||||
|
||||
this._onBlur = this._onBlur.bind(this);
|
||||
this._onKeyPress = this._onKeyPress.bind(this);
|
||||
|
@ -208,6 +217,8 @@ function InplaceEditor(aOptions, aEvent)
|
|||
|
||||
exports.InplaceEditor = InplaceEditor;
|
||||
|
||||
InplaceEditor.CONTENT_TYPES = CONTENT_TYPES;
|
||||
|
||||
InplaceEditor.prototype = {
|
||||
_createInput: function InplaceEditor_createEditor()
|
||||
{
|
||||
|
@ -679,6 +690,10 @@ InplaceEditor.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
if (this.popup) {
|
||||
this.popup.hidePopup();
|
||||
}
|
||||
|
||||
this._applied = true;
|
||||
|
||||
if (this.done) {
|
||||
|
@ -732,9 +747,31 @@ InplaceEditor.prototype = {
|
|||
increment *= smallIncrement;
|
||||
}
|
||||
|
||||
let cycling = false;
|
||||
if (increment && this._incrementValue(increment) ) {
|
||||
this._updateSize();
|
||||
prevent = true;
|
||||
} else if (increment && this.popup && this.popup.isOpen) {
|
||||
cycling = true;
|
||||
prevent = true;
|
||||
if (increment > 0) {
|
||||
this.popup.selectPreviousItem();
|
||||
} else {
|
||||
this.popup.selectNextItem();
|
||||
}
|
||||
this.input.value = this.popup.selectedItem.label;
|
||||
this._updateSize();
|
||||
}
|
||||
|
||||
if (aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_BACK_SPACE ||
|
||||
aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_DELETE ||
|
||||
aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_LEFT ||
|
||||
aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RIGHT) {
|
||||
if (this.popup && this.popup.isOpen) {
|
||||
this.popup.hidePopup();
|
||||
}
|
||||
} else if (!cycling) {
|
||||
this._maybeSuggestCompletion();
|
||||
}
|
||||
|
||||
if (this.multiline &&
|
||||
|
@ -756,6 +793,9 @@ InplaceEditor.prototype = {
|
|||
direction = null;
|
||||
}
|
||||
|
||||
// Now we don't want to suggest anything as we are moving out.
|
||||
this._preventSuggestions = true;
|
||||
|
||||
let input = this.input;
|
||||
|
||||
this._apply();
|
||||
|
@ -775,6 +815,8 @@ InplaceEditor.prototype = {
|
|||
this._clear();
|
||||
} else if (aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE) {
|
||||
// Cancel and blur ourselves.
|
||||
// Now we don't want to suggest anything as we are moving out.
|
||||
this._preventSuggestions = true;
|
||||
prevent = true;
|
||||
this.cancelled = true;
|
||||
this._apply();
|
||||
|
@ -821,6 +863,79 @@ InplaceEditor.prototype = {
|
|||
if (this.change) {
|
||||
this.change(this.input.value.trim());
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles displaying suggestions based on the current input.
|
||||
*/
|
||||
_maybeSuggestCompletion: function() {
|
||||
// Since we are calling this method from a keypress event handler, the
|
||||
// |input.value| does not include currently typed character. Thus we perform
|
||||
// this method async.
|
||||
this.doc.defaultView.setTimeout(() => {
|
||||
if (this._preventSuggestions) {
|
||||
this._preventSuggestions = false;
|
||||
return;
|
||||
}
|
||||
if (this.contentType == CONTENT_TYPES.PLAIN_TEXT) {
|
||||
return;
|
||||
}
|
||||
|
||||
let input = this.input;
|
||||
// Input can be null in cases when you intantaneously switch out of it.
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
let query = input.value.slice(0, input.selectionStart);
|
||||
if (!query) {
|
||||
return;
|
||||
}
|
||||
|
||||
let list = [];
|
||||
if (this.contentType == CONTENT_TYPES.CSS_PROPERTY) {
|
||||
list = CSSPropertyList;
|
||||
}
|
||||
|
||||
list.some(item => {
|
||||
if (item.startsWith(query)) {
|
||||
input.value = item;
|
||||
input.setSelectionRange(query.length, item.length);
|
||||
this._updateSize();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!this.popup) {
|
||||
return;
|
||||
}
|
||||
let finalList = [];
|
||||
let length = list.length;
|
||||
for (let i = 0, count = 0; i < length && count < MAX_POPUP_ENTRIES; i++) {
|
||||
if (list[i].startsWith(query)) {
|
||||
count++;
|
||||
finalList.push({
|
||||
preLabel: query,
|
||||
label: list[i]
|
||||
});
|
||||
}
|
||||
else if (count > 0) {
|
||||
// Since count was incremented, we had already crossed the entries
|
||||
// which would have started with query, assuming that list is sorted.
|
||||
break;
|
||||
}
|
||||
else if (list[i][0] > query[0]) {
|
||||
// We have crossed all possible matches alphabetically.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (finalList.length > 1) {
|
||||
this.popup.setItems(finalList);
|
||||
this.popup.openPopup(this.input);
|
||||
} else {
|
||||
this.popup.hidePopup();
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -849,3 +964,8 @@ function moveFocus(aWin, aDirection)
|
|||
XPCOMUtils.defineLazyGetter(this, "focusManager", function() {
|
||||
return Services.focus;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "CSSPropertyList", function() {
|
||||
let domUtils = Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
||||
return domUtils.getCSSPropertyNames(domUtils.INCLUDE_ALIASES).sort();
|
||||
});
|
||||
|
|
|
@ -876,6 +876,13 @@ function CssRuleView(aDoc, aStore)
|
|||
this._boundCopy = this._onCopy.bind(this);
|
||||
this.element.addEventListener("copy", this._boundCopy);
|
||||
|
||||
let options = {
|
||||
fixedWidth: true,
|
||||
autoSelect: true,
|
||||
theme: "auto"
|
||||
};
|
||||
this.popup = new AutocompletePopup(aDoc.defaultView.parent.document, options);
|
||||
|
||||
this._showEmpty();
|
||||
}
|
||||
|
||||
|
@ -902,6 +909,8 @@ CssRuleView.prototype = {
|
|||
if (this.element.parentNode) {
|
||||
this.element.parentNode.removeChild(this.element);
|
||||
}
|
||||
|
||||
this.popup.destroy();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1270,7 +1279,9 @@ RuleEditor.prototype = {
|
|||
element: this.newPropSpan,
|
||||
done: this._onNewProperty,
|
||||
destroy: this._newPropertyDestroy,
|
||||
advanceChars: ":"
|
||||
advanceChars: ":",
|
||||
contentType: InplaceEditor.CONTENT_TYPES.CSS_PROPERTY,
|
||||
popup: this.ruleView.popup
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -1322,6 +1333,7 @@ RuleEditor.prototype = {
|
|||
function TextPropertyEditor(aRuleEditor, aProperty)
|
||||
{
|
||||
this.doc = aRuleEditor.doc;
|
||||
this.popup = aRuleEditor.ruleView.popup;
|
||||
this.prop = aProperty;
|
||||
this.prop.editor = this;
|
||||
this.browserWindow = this.doc.defaultView.top;
|
||||
|
@ -1390,7 +1402,9 @@ TextPropertyEditor.prototype = {
|
|||
start: this._onStartEditing,
|
||||
element: this.nameSpan,
|
||||
done: this._onNameDone,
|
||||
advanceChars: ':'
|
||||
advanceChars: ':',
|
||||
contentType: InplaceEditor.CONTENT_TYPES.CSS_PROPERTY,
|
||||
popup: this.popup
|
||||
});
|
||||
|
||||
appendText(this.nameContainer, ": ");
|
||||
|
@ -1873,3 +1887,7 @@ XPCOMUtils.defineLazyGetter(this, "_strings", function() {
|
|||
XPCOMUtils.defineLazyGetter(this, "domUtils", function() {
|
||||
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "AutocompletePopup", function() {
|
||||
return Cu.import("resource:///modules/devtools/AutocompletePopup.jsm", {}).AutocompletePopup;
|
||||
});
|
||||
|
|
|
@ -38,6 +38,8 @@ MOCHITEST_BROWSER_FILES = \
|
|||
browser_computedview_734259_style_editor_link.js \
|
||||
browser_computedview_copy.js\
|
||||
browser_styleinspector_bug_677930_urls_clickable.js \
|
||||
browser_bug893965_css_property_completion_new_property.js \
|
||||
browser_bug893965_css_property_completion_existing_property.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that CSS property names are autocompleted and cycled correctly.
|
||||
|
||||
const MAX_ENTRIES = 10;
|
||||
|
||||
let doc;
|
||||
let inspector;
|
||||
let ruleViewWindow;
|
||||
let editor;
|
||||
let state;
|
||||
// format :
|
||||
// [
|
||||
// what key to press,
|
||||
// expected input box value after keypress,
|
||||
// selectedIndex of the popup,
|
||||
// total items in the popup
|
||||
// ]
|
||||
let testData = [
|
||||
["VK_RIGHT", "border", -1, 0],
|
||||
["-","border-bottom", 0, 10],
|
||||
["b","border-bottom", 0, 6],
|
||||
["VK_BACK_SPACE", "border-b", -1, 0],
|
||||
["VK_BACK_SPACE", "border-", -1, 0],
|
||||
["VK_BACK_SPACE", "border", -1, 0],
|
||||
["VK_BACK_SPACE", "borde", -1, 0],
|
||||
["VK_BACK_SPACE", "bord", -1, 0],
|
||||
["VK_BACK_SPACE", "bor", -1, 0],
|
||||
["VK_BACK_SPACE", "bo", -1, 0],
|
||||
["VK_BACK_SPACE", "b", -1, 0],
|
||||
["VK_BACK_SPACE", "", -1, 0],
|
||||
["d", "direction", 0, 3],
|
||||
["VK_DOWN", "display", 1, 3],
|
||||
["VK_DOWN", "dominant-baseline", 2, 3],
|
||||
["VK_DOWN", "direction", 0, 3],
|
||||
["VK_DOWN", "display", 1, 3],
|
||||
["VK_UP", "direction", 0, 3],
|
||||
["VK_UP", "dominant-baseline", 2, 3],
|
||||
["VK_UP", "display", 1, 3],
|
||||
["VK_BACK_SPACE", "displa", -1, 0],
|
||||
["VK_BACK_SPACE", "displ", -1, 0],
|
||||
["VK_BACK_SPACE", "disp", -1, 0],
|
||||
["VK_BACK_SPACE", "dis", -1, 0],
|
||||
["VK_BACK_SPACE", "di", -1, 0],
|
||||
["VK_BACK_SPACE", "d", -1, 0],
|
||||
["i", "direction", 0, 2],
|
||||
["s", "display", -1, 0],
|
||||
["VK_BACK_SPACE", "dis", -1, 0],
|
||||
["VK_BACK_SPACE", "di", -1, 0],
|
||||
["VK_BACK_SPACE", "d", -1, 0],
|
||||
["VK_BACK_SPACE", "", -1, 0],
|
||||
["f", "fill", 0, MAX_ENTRIES],
|
||||
["i", "fill", 0, 4],
|
||||
["VK_ESCAPE", null, -1, 0],
|
||||
];
|
||||
|
||||
function openRuleView()
|
||||
{
|
||||
var target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
|
||||
inspector = toolbox.getCurrentPanel();
|
||||
inspector.sidebar.select("ruleview");
|
||||
|
||||
// Highlight a node.
|
||||
let node = content.document.getElementsByTagName("h1")[0];
|
||||
inspector.selection.setNode(node);
|
||||
|
||||
inspector.sidebar.once("ruleview-ready", testCompletion);
|
||||
});
|
||||
}
|
||||
|
||||
function testCompletion()
|
||||
{
|
||||
ruleViewWindow = inspector.sidebar.getWindowForTab("ruleview");
|
||||
let brace = ruleViewWindow.document.querySelector(".ruleview-propertyname");
|
||||
|
||||
waitForEditorFocus(brace.parentNode, function onNewElement(aEditor) {
|
||||
editor = aEditor;
|
||||
editor.input.addEventListener("keypress", checkState, false);
|
||||
checkStateAndMoveOn(0);
|
||||
});
|
||||
|
||||
brace.click();
|
||||
}
|
||||
|
||||
function checkStateAndMoveOn(index) {
|
||||
if (index == testData.length) {
|
||||
finishUp();
|
||||
return;
|
||||
}
|
||||
|
||||
let [key] = testData[index];
|
||||
state = index;
|
||||
|
||||
info("pressing key " + key + " to get result: [" + testData[index].slice(1) +
|
||||
"] for state " + state);
|
||||
EventUtils.synthesizeKey(key, {}, ruleViewWindow);
|
||||
}
|
||||
|
||||
function checkState(event) {
|
||||
// The keypress handler is async and can take some time to compute, filter and
|
||||
// display the popup and autocompletion so we need to use setTimeout here.
|
||||
window.setTimeout(function() {
|
||||
info("After keypress for state " + state);
|
||||
let [key, completion, index, total] = testData[state];
|
||||
if (completion != null) {
|
||||
is(editor.input.value, completion,
|
||||
"Correct value is autocompleted for state " + state);
|
||||
}
|
||||
if (total == 0) {
|
||||
ok(!(editor.popup && editor.popup.isOpen), "Popup is closed for state " +
|
||||
state);
|
||||
}
|
||||
else {
|
||||
ok(editor.popup._panel.state == "open" ||
|
||||
editor.popup._panel.state == "showing",
|
||||
"Popup is open for state " + state);
|
||||
is(editor.popup.getItems().length, total,
|
||||
"Number of suggestions match for state " + state);
|
||||
is(editor.popup.selectedIndex, index,
|
||||
"Correct item is selected for state " + state);
|
||||
}
|
||||
checkStateAndMoveOn(state + 1);
|
||||
}, 200);
|
||||
}
|
||||
|
||||
function finishUp()
|
||||
{
|
||||
doc = inspector = editor = ruleViewWindow = state = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
|
||||
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
|
||||
doc = content.document;
|
||||
doc.title = "Rule View Test";
|
||||
waitForFocus(openRuleView, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,<h1 style='border: 1px solid red'>Filename" +
|
||||
": browser_bug893965_css_property_completion_existing_property.js</h1>";
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that CSS property names are autocompleted and cycled correctly.
|
||||
|
||||
const MAX_ENTRIES = 10;
|
||||
|
||||
let doc;
|
||||
let inspector;
|
||||
let ruleViewWindow;
|
||||
let editor;
|
||||
let state;
|
||||
// format :
|
||||
// [
|
||||
// what key to press,
|
||||
// expected input box value after keypress,
|
||||
// selectedIndex of the popup,
|
||||
// total items in the popup
|
||||
// ]
|
||||
let testData = [
|
||||
["d", "direction", 0, 3],
|
||||
["VK_DOWN", "display", 1, 3],
|
||||
["VK_DOWN", "dominant-baseline", 2, 3],
|
||||
["VK_DOWN", "direction", 0, 3],
|
||||
["VK_DOWN", "display", 1, 3],
|
||||
["VK_UP", "direction", 0, 3],
|
||||
["VK_UP", "dominant-baseline", 2, 3],
|
||||
["VK_UP", "display", 1, 3],
|
||||
["VK_BACK_SPACE", "displa", -1, 0],
|
||||
["VK_BACK_SPACE", "displ", -1, 0],
|
||||
["VK_BACK_SPACE", "disp", -1, 0],
|
||||
["VK_BACK_SPACE", "dis", -1, 0],
|
||||
["VK_BACK_SPACE", "di", -1, 0],
|
||||
["VK_BACK_SPACE", "d", -1, 0],
|
||||
["i", "direction", 0, 2],
|
||||
["s", "display", -1, 0],
|
||||
["VK_BACK_SPACE", "dis", -1, 0],
|
||||
["VK_BACK_SPACE", "di", -1, 0],
|
||||
["VK_BACK_SPACE", "d", -1, 0],
|
||||
["VK_BACK_SPACE", "", -1, 0],
|
||||
["f", "fill", 0, MAX_ENTRIES],
|
||||
["i", "fill", 0, 4],
|
||||
["VK_ESCAPE", null, -1, 0],
|
||||
];
|
||||
|
||||
function openRuleView()
|
||||
{
|
||||
var target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
|
||||
inspector = toolbox.getCurrentPanel();
|
||||
inspector.sidebar.select("ruleview");
|
||||
|
||||
// Highlight a node.
|
||||
let node = content.document.getElementsByTagName("h1")[0];
|
||||
inspector.selection.setNode(node);
|
||||
|
||||
inspector.sidebar.once("ruleview-ready", testCompletion);
|
||||
});
|
||||
}
|
||||
|
||||
function testCompletion()
|
||||
{
|
||||
ruleViewWindow = inspector.sidebar.getWindowForTab("ruleview");
|
||||
let brace = ruleViewWindow.document.querySelector(".ruleview-ruleclose");
|
||||
|
||||
waitForEditorFocus(brace.parentNode, function onNewElement(aEditor) {
|
||||
editor = aEditor;
|
||||
editor.input.addEventListener("keypress", checkState, false);
|
||||
checkStateAndMoveOn(0);
|
||||
});
|
||||
|
||||
brace.click();
|
||||
}
|
||||
|
||||
function checkStateAndMoveOn(index) {
|
||||
if (index == testData.length) {
|
||||
finishUp();
|
||||
return;
|
||||
}
|
||||
|
||||
let [key] = testData[index];
|
||||
state = index;
|
||||
|
||||
info("pressing key " + key + " to get result: [" + testData[index].slice(1) +
|
||||
"] for state " + state);
|
||||
EventUtils.synthesizeKey(key, {}, ruleViewWindow);
|
||||
}
|
||||
|
||||
function checkState(event) {
|
||||
// The keypress handler is async and can take some time to compute, filter and
|
||||
// display the popup and autocompletion so we need to use setTimeout here.
|
||||
window.setTimeout(function() {
|
||||
info("After keypress for state " + state);
|
||||
let [key, completion, index, total] = testData[state];
|
||||
if (completion != null) {
|
||||
is(editor.input.value, completion,
|
||||
"Correct value is autocompleted for state " + state);
|
||||
}
|
||||
if (total == 0) {
|
||||
ok(!(editor.popup && editor.popup.isOpen), "Popup is closed for state " +
|
||||
state);
|
||||
}
|
||||
else {
|
||||
ok(editor.popup._panel.state == "open" ||
|
||||
editor.popup._panel.state == "showing",
|
||||
"Popup is open for state " + state);
|
||||
is(editor.popup.getItems().length, total,
|
||||
"Number of suggestions match for state " + state);
|
||||
is(editor.popup.selectedIndex, index,
|
||||
"Correct item is selected for state " + state);
|
||||
}
|
||||
checkStateAndMoveOn(state + 1);
|
||||
}, 200);
|
||||
}
|
||||
|
||||
function finishUp()
|
||||
{
|
||||
doc = inspector = editor = ruleViewWindow = state = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
|
||||
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
|
||||
doc = content.document;
|
||||
doc.title = "Rule View Test";
|
||||
waitForFocus(openRuleView, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,<h1 style='border: 1px solid red'>Filename:" +
|
||||
"browser_bug893965_css_property_completion_new_property.js</h1>";
|
||||
}
|
|
@ -69,7 +69,6 @@ function consoleOpened(aHud) {
|
|||
is(popup.selectedIndex, 17,
|
||||
"Index of the first item from bottom is selected.");
|
||||
EventUtils.synthesizeKey("VK_DOWN", {});
|
||||
EventUtils.synthesizeKey("VK_DOWN", {});
|
||||
|
||||
let prefix = jsterm.inputNode.value.replace(/[\S]/g, " ");
|
||||
|
||||
|
@ -123,7 +122,6 @@ function popupHideAfterTab()
|
|||
|
||||
is(popup.selectedIndex, 17, "First index from bottom is selected");
|
||||
EventUtils.synthesizeKey("VK_DOWN", {});
|
||||
EventUtils.synthesizeKey("VK_DOWN", {});
|
||||
|
||||
let prefix = jsterm.inputNode.value.replace(/[\S]/g, " ");
|
||||
|
||||
|
@ -169,7 +167,6 @@ function testReturnKey()
|
|||
|
||||
is(popup.selectedIndex, 17, "First index from bottom is selected");
|
||||
EventUtils.synthesizeKey("VK_DOWN", {});
|
||||
EventUtils.synthesizeKey("VK_DOWN", {});
|
||||
|
||||
let prefix = jsterm.inputNode.value.replace(/[\S]/g, " ");
|
||||
|
||||
|
@ -292,7 +289,6 @@ function testCompletionInText()
|
|||
ok(popup.isOpen, "popup is open");
|
||||
is(popup.itemCount, 2, "popup.itemCount is correct");
|
||||
|
||||
EventUtils.synthesizeKey("VK_DOWN", {});
|
||||
EventUtils.synthesizeKey("VK_DOWN", {});
|
||||
is(popup.selectedIndex, 0, "popup.selectedIndex is correct");
|
||||
ok(!completeNode.value, "completeNode.value is empty");
|
||||
|
|
|
@ -64,10 +64,10 @@ function consoleOpened(HUD) {
|
|||
is(popup.selectedIndex, 2, "index 2 is selected");
|
||||
is(popup.selectedItem, items[2], "item2 is selected");
|
||||
|
||||
ok(!popup.selectNextItem(), "selectPreviousItem() works");
|
||||
ok(popup.selectNextItem(), "selectPreviousItem() works");
|
||||
|
||||
is(popup.selectedIndex, -1, "no index is selected");
|
||||
ok(!popup.selectedItem, "no item is selected");
|
||||
is(popup.selectedIndex, 0, "index 0 is selected");
|
||||
is(popup.selectedItem, items[0], "item0 is selected");
|
||||
|
||||
items.push({label: "label3", value: "value3"});
|
||||
popup.appendItem(items[3]);
|
||||
|
|
|
@ -66,21 +66,21 @@ function testCompletion(hud) {
|
|||
yield undefined;
|
||||
|
||||
is(input.value, "document.getElem", "'document.getElem' completion");
|
||||
is(jsterm.completeNode.value, "", "'document.getElem' completion");
|
||||
is(jsterm.completeNode.value, " entsByTagNameNS", "'document.getElem' completion");
|
||||
|
||||
// Test pressing tab another time.
|
||||
jsterm.complete(jsterm.COMPLETE_FORWARD, testNext);
|
||||
yield undefined;
|
||||
|
||||
is(input.value, "document.getElem", "'document.getElem' completion");
|
||||
is(jsterm.completeNode.value, " entsByTagNameNS", "'document.getElem' another tab completion");
|
||||
is(jsterm.completeNode.value, " entsByTagName", "'document.getElem' another tab completion");
|
||||
|
||||
// Test pressing shift_tab.
|
||||
jsterm.complete(jsterm.COMPLETE_BACKWARD, testNext);
|
||||
yield undefined;
|
||||
|
||||
is(input.value, "document.getElem", "'document.getElem' untab completion");
|
||||
is(jsterm.completeNode.value, "", "'document.getElem' completion");
|
||||
is(jsterm.completeNode.value, " entsByTagNameNS", "'document.getElem' completion");
|
||||
|
||||
jsterm.clearOutput();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче