зеркало из https://github.com/mozilla/gecko-dev.git
merge fx-team to mozilla-central a=merge
This commit is contained in:
Коммит
3ed844e5b9
|
@ -699,7 +699,6 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
|||
// previously set, revert to using an empty string by default.
|
||||
this._cbTextbox.value = expr;
|
||||
|
||||
|
||||
function openPopup() {
|
||||
// Show the conditional expression panel. The popup arrow should be pointing
|
||||
// at the line number node in the breakpoint item view.
|
||||
|
|
|
@ -9,6 +9,7 @@ support-files =
|
|||
addon4.xpi
|
||||
addon5.xpi
|
||||
addon-webext-contentscript.xpi
|
||||
addon-source/browser_dbg_addon5/*
|
||||
code_binary_search.coffee
|
||||
code_binary_search.js
|
||||
code_binary_search.map
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
|
||||
// Test that the we can see console messages from the add-on
|
||||
|
||||
const ADDON_URL = EXAMPLE_URL + "addon4.xpi";
|
||||
const ADDON_ID = "browser_dbg_addon4@tests.mozilla.org";
|
||||
const ADDON_PATH = "addon4.xpi";
|
||||
|
||||
function getCachedMessages(webConsole) {
|
||||
let deferred = promise.defer();
|
||||
|
@ -21,8 +22,8 @@ function getCachedMessages(webConsole) {
|
|||
|
||||
function test() {
|
||||
Task.spawn(function* () {
|
||||
let addon = yield addAddon(ADDON_URL);
|
||||
let addonDebugger = yield initAddonDebugger(ADDON_URL);
|
||||
let addon = yield addTemporaryAddon(ADDON_PATH);
|
||||
let addonDebugger = yield initAddonDebugger(ADDON_ID);
|
||||
|
||||
let webConsole = addonDebugger.webConsole;
|
||||
let messages = yield getCachedMessages(webConsole);
|
||||
|
|
|
@ -5,16 +5,19 @@
|
|||
|
||||
// Make sure the add-on actor can see loaded JS Modules from an add-on
|
||||
|
||||
const ADDON_URL = EXAMPLE_URL + "addon5.xpi";
|
||||
const ADDON_ID = "browser_dbg_addon5@tests.mozilla.org";
|
||||
const ADDON_PATH = "addon-source/browser_dbg_addon5/";
|
||||
const ADDON_URL = getTemporaryAddonURLFromPath(ADDON_PATH);
|
||||
|
||||
function test() {
|
||||
Task.spawn(function* () {
|
||||
let addon = yield addAddon(ADDON_URL);
|
||||
let addon = yield addTemporaryAddon(ADDON_PATH);
|
||||
let tab1 = yield addTab("chrome://browser_dbg_addon5/content/test.xul");
|
||||
|
||||
let addonDebugger = yield initAddonDebugger(ADDON_URL);
|
||||
let addonDebugger = yield initAddonDebugger(ADDON_ID);
|
||||
|
||||
is(addonDebugger.title, `Developer Tools - Test unpacked add-on with JS Modules - ${ADDON_URL}`,
|
||||
is(addonDebugger.title,
|
||||
`Developer Tools - Test unpacked add-on with JS Modules - ${ADDON_URL}`,
|
||||
"Saw the right toolbox title.");
|
||||
|
||||
// Check the inital list of sources is correct
|
||||
|
@ -25,7 +28,7 @@ function test() {
|
|||
|
||||
let sources = groups[0].sources;
|
||||
is(sources.length, 3, "Should be three sources");
|
||||
ok(sources[0].url.endsWith("/browser_dbg_addon5@tests.mozilla.org/bootstrap.js"), "correct url for bootstrap code");
|
||||
ok(sources[0].url.endsWith("/browser_dbg_addon5/bootstrap.js"), "correct url for bootstrap code");
|
||||
is(sources[0].label, "bootstrap.js", "correct label for bootstrap code");
|
||||
is(sources[1].url, "resource://browser_dbg_addon5/test.jsm", "correct url for addon code");
|
||||
is(sources[1].label, "test.jsm", "correct label for addon code");
|
||||
|
@ -43,7 +46,7 @@ function test() {
|
|||
|
||||
sources = groups[0].sources;
|
||||
is(sources.length, 5, "Should be five sources");
|
||||
ok(sources[0].url.endsWith("/browser_dbg_addon5@tests.mozilla.org/bootstrap.js"), "correct url for bootstrap code");
|
||||
ok(sources[0].url.endsWith("/browser_dbg_addon5/bootstrap.js"), "correct url for bootstrap code");
|
||||
is(sources[0].label, "bootstrap.js", "correct label for bootstrap code");
|
||||
is(sources[1].url, "resource://browser_dbg_addon5/test.jsm", "correct url for addon code");
|
||||
is(sources[1].label, "test.jsm", "correct label for addon code");
|
||||
|
|
|
@ -5,14 +5,16 @@
|
|||
|
||||
// Make sure the add-on actor can see loaded JS Modules from an add-on
|
||||
|
||||
const ADDON_URL = EXAMPLE_URL + "addon4.xpi";
|
||||
const ADDON_ID = "browser_dbg_addon4@tests.mozilla.org";
|
||||
const ADDON_PATH = "addon4.xpi";
|
||||
const ADDON_URL = getTemporaryAddonURLFromPath(ADDON_PATH);
|
||||
|
||||
function test() {
|
||||
Task.spawn(function* () {
|
||||
let addon = yield addAddon(ADDON_URL);
|
||||
let addon = yield addTemporaryAddon(ADDON_PATH);
|
||||
let tab1 = yield addTab("chrome://browser_dbg_addon4/content/test.xul");
|
||||
|
||||
let addonDebugger = yield initAddonDebugger(ADDON_URL);
|
||||
let addonDebugger = yield initAddonDebugger(ADDON_ID);
|
||||
|
||||
is(addonDebugger.title, `Developer Tools - Test add-on with JS Modules - ${ADDON_URL}`,
|
||||
"Saw the right toolbox title.");
|
||||
|
@ -25,7 +27,7 @@ function test() {
|
|||
|
||||
let sources = groups[0].sources;
|
||||
is(sources.length, 3, "Should be three sources");
|
||||
ok(sources[0].url.endsWith("/browser_dbg_addon4@tests.mozilla.org.xpi!/bootstrap.js"), "correct url for bootstrap code");
|
||||
ok(sources[0].url.endsWith("/addon4.xpi!/bootstrap.js"), "correct url for bootstrap code");
|
||||
is(sources[0].label, "bootstrap.js", "correct label for bootstrap code");
|
||||
is(sources[1].url, "resource://browser_dbg_addon4/test.jsm", "correct url for addon code");
|
||||
is(sources[1].label, "test.jsm", "correct label for addon code");
|
||||
|
@ -43,7 +45,7 @@ function test() {
|
|||
|
||||
sources = groups[0].sources;
|
||||
is(sources.length, 5, "Should be five sources");
|
||||
ok(sources[0].url.endsWith("/browser_dbg_addon4@tests.mozilla.org.xpi!/bootstrap.js"), "correct url for bootstrap code");
|
||||
ok(sources[0].url.endsWith("/addon4.xpi!/bootstrap.js"), "correct url for bootstrap code");
|
||||
is(sources[0].label, "bootstrap.js", "correct label for bootstrap code");
|
||||
is(sources[1].url, "resource://browser_dbg_addon4/test.jsm", "correct url for addon code");
|
||||
is(sources[1].label, "test.jsm", "correct label for addon code");
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
// Ensure that only panels that are relevant to the addon debugger
|
||||
// display in the toolbox
|
||||
|
||||
const ADDON_URL = EXAMPLE_URL + "addon3.xpi";
|
||||
const ADDON_ID = "jid1-ami3akps3baaeg@jetpack";
|
||||
const ADDON_PATH = "addon3.xpi";
|
||||
|
||||
var gAddon, gClient, gThreadClient, gDebugger, gSources;
|
||||
var PREFS = [
|
||||
|
@ -21,8 +22,8 @@ function test() {
|
|||
// Store and enable all optional dev tools panels
|
||||
yield pushPrefs(...PREFS);
|
||||
|
||||
let addon = yield addAddon(ADDON_URL);
|
||||
let addonDebugger = yield initAddonDebugger(ADDON_URL);
|
||||
let addon = yield addTemporaryAddon(ADDON_PATH);
|
||||
let addonDebugger = yield initAddonDebugger(ADDON_ID);
|
||||
|
||||
// Check only valid tabs are shown
|
||||
let tabs = addonDebugger.frame.contentDocument.getElementById("toolbox-tabs").children;
|
||||
|
|
|
@ -6,13 +6,16 @@
|
|||
// Ensure that the sources listed when debugging an addon are either from the
|
||||
// addon itself, or the SDK, with proper groups and labels.
|
||||
|
||||
const ADDON_URL = EXAMPLE_URL + "addon3.xpi";
|
||||
const ADDON_ID = "jid1-ami3akps3baaeg@jetpack";
|
||||
const ADDON_PATH = "addon3.xpi";
|
||||
const ADDON_URL = getTemporaryAddonURLFromPath(ADDON_PATH);
|
||||
|
||||
var gClient;
|
||||
|
||||
function test() {
|
||||
Task.spawn(function* () {
|
||||
let addon = yield addAddon(ADDON_URL);
|
||||
let addonDebugger = yield initAddonDebugger(ADDON_URL);
|
||||
let addon = yield addTemporaryAddon(ADDON_PATH);
|
||||
let addonDebugger = yield initAddonDebugger(ADDON_ID);
|
||||
|
||||
is(addonDebugger.title, `Developer Tools - browser_dbg_addon3 - ${ADDON_URL}`,
|
||||
"Saw the right toolbox title.");
|
||||
|
@ -25,7 +28,7 @@ function test() {
|
|||
|
||||
let sources = groups[0].sources;
|
||||
is(sources.length, 2, "Should be two sources");
|
||||
ok(sources[0].url.endsWith("/jid1-ami3akps3baaeg@jetpack.xpi!/bootstrap.js"), "correct url for bootstrap code");
|
||||
ok(sources[0].url.endsWith("/addon3.xpi!/bootstrap.js"), "correct url for bootstrap code");
|
||||
is(sources[0].label, "bootstrap.js", "correct label for bootstrap code");
|
||||
is(sources[1].url, "resource://jid1-ami3akps3baaeg-at-jetpack/browser_dbg_addon3/lib/main.js", "correct url for add-on code");
|
||||
is(sources[1].label, "resources/browser_dbg_addon3/lib/main.js", "correct label for add-on code");
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
// Test that the Addon Debugger works when devtools.debugger.workers is enabled.
|
||||
// Workers controller cannot be used when debugging an Addon actor.
|
||||
|
||||
const ADDON_URL = EXAMPLE_URL + "addon3.xpi";
|
||||
const ADDON_ID = "jid1-ami3akps3baaeg@jetpack";
|
||||
const ADDON_PATH = "addon3.xpi";
|
||||
const ADDON_URL = getTemporaryAddonURLFromPath(ADDON_PATH);
|
||||
|
||||
function test() {
|
||||
Task.spawn(function* () {
|
||||
|
@ -19,8 +21,8 @@ function test() {
|
|||
}, resolve);
|
||||
});
|
||||
|
||||
let addon = yield addAddon(ADDON_URL);
|
||||
let addonDebugger = yield initAddonDebugger(ADDON_URL);
|
||||
let addon = yield addTemporaryAddon(ADDON_PATH);
|
||||
let addonDebugger = yield initAddonDebugger(ADDON_ID);
|
||||
|
||||
is(addonDebugger.title,
|
||||
`Developer Tools - browser_dbg_addon3 - ${ADDON_URL}`,
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
|
||||
// Make sure we can attach to addon actors.
|
||||
|
||||
const ADDON3_URL = EXAMPLE_URL + "addon3.xpi";
|
||||
const ADDON3_PATH = "addon3.xpi";
|
||||
const ADDON3_ID = "jid1-ami3akps3baaeg@jetpack";
|
||||
const ADDON_MODULE_URL = "resource://jid1-ami3akps3baaeg-at-jetpack/browser_dbg_addon3/lib/main.js";
|
||||
|
||||
var gAddon, gClient, gThreadClient;
|
||||
|
@ -23,7 +24,7 @@ function test() {
|
|||
"Root actor should identify itself as a browser.");
|
||||
|
||||
installAddon()
|
||||
.then(attachAddonActorForUrl.bind(null, gClient, ADDON3_URL))
|
||||
.then(attachAddonActorForId.bind(null, gClient, ADDON3_ID))
|
||||
.then(attachAddonThread)
|
||||
.then(testDebugger)
|
||||
.then(testSources)
|
||||
|
@ -37,13 +38,13 @@ function test() {
|
|||
}
|
||||
|
||||
function installAddon() {
|
||||
return addAddon(ADDON3_URL).then(aAddon => {
|
||||
return addTemporaryAddon(ADDON3_PATH).then(aAddon => {
|
||||
gAddon = aAddon;
|
||||
});
|
||||
}
|
||||
|
||||
function attachAddonThread([aGrip, aResponse]) {
|
||||
info("attached addon actor for URL");
|
||||
info("attached addon actor for Addon ID");
|
||||
let deferred = promise.defer();
|
||||
|
||||
gClient.attachThread(aResponse.threadActor, (aResponse, aThreadClient) => {
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
* Check extension-added global actor API.
|
||||
*/
|
||||
|
||||
const CHROME_URL = "chrome://mochitests/content/browser/devtools/client/debugger/test/mochitest/";
|
||||
const ACTORS_URL = CHROME_URL + "testactors.js";
|
||||
|
||||
function test() {
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
/**
|
||||
* Make sure the listAddons request works as specified.
|
||||
*/
|
||||
const ADDON1_URL = EXAMPLE_URL + "addon1.xpi";
|
||||
const ADDON2_URL = EXAMPLE_URL + "addon2.xpi";
|
||||
const ADDON1_ID = "jid1-oBAwBoE5rSecNg@jetpack";
|
||||
const ADDON1_PATH = "addon1.xpi";
|
||||
const ADDON2_ID = "jid1-qjtzNGV8xw5h2A@jetpack";
|
||||
const ADDON2_PATH = "addon2.xpi";
|
||||
|
||||
var gAddon1, gAddon1Actor, gAddon2, gAddon2Actor, gClient;
|
||||
|
||||
|
@ -42,10 +44,10 @@ function testFirstAddon() {
|
|||
addonListChanged = true;
|
||||
});
|
||||
|
||||
return addAddon(ADDON1_URL).then(aAddon => {
|
||||
return addTemporaryAddon(ADDON1_PATH).then(aAddon => {
|
||||
gAddon1 = aAddon;
|
||||
|
||||
return getAddonActorForUrl(gClient, ADDON1_URL).then(aGrip => {
|
||||
return getAddonActorForId(gClient, ADDON1_ID).then(aGrip => {
|
||||
ok(!addonListChanged, "Should not yet be notified that list of addons changed.");
|
||||
ok(aGrip, "Should find an addon actor for addon1.");
|
||||
gAddon1Actor = aGrip.actor;
|
||||
|
@ -59,11 +61,11 @@ function testSecondAddon() {
|
|||
addonListChanged = true;
|
||||
});
|
||||
|
||||
return addAddon(ADDON2_URL).then(aAddon => {
|
||||
return addTemporaryAddon(ADDON2_PATH).then(aAddon => {
|
||||
gAddon2 = aAddon;
|
||||
|
||||
return getAddonActorForUrl(gClient, ADDON1_URL).then(aFirstGrip => {
|
||||
return getAddonActorForUrl(gClient, ADDON2_URL).then(aSecondGrip => {
|
||||
return getAddonActorForId(gClient, ADDON1_ID).then(aFirstGrip => {
|
||||
return getAddonActorForId(gClient, ADDON2_ID).then(aSecondGrip => {
|
||||
ok(addonListChanged, "Should be notified that list of addons changed.");
|
||||
is(aFirstGrip.actor, gAddon1Actor, "First addon's actor shouldn't have changed.");
|
||||
ok(aSecondGrip, "Should find a addon actor for the second addon.");
|
||||
|
@ -79,8 +81,8 @@ function testRemoveFirstAddon() {
|
|||
addonListChanged = true;
|
||||
});
|
||||
|
||||
removeAddon(gAddon1).then(() => {
|
||||
return getAddonActorForUrl(gClient, ADDON1_URL).then(aGrip => {
|
||||
return removeAddon(gAddon1).then(() => {
|
||||
return getAddonActorForId(gClient, ADDON1_ID).then(aGrip => {
|
||||
ok(addonListChanged, "Should be notified that list of addons changed.");
|
||||
ok(!aGrip, "Shouldn't find a addon actor for the first addon anymore.");
|
||||
});
|
||||
|
@ -93,8 +95,8 @@ function testRemoveSecondAddon() {
|
|||
addonListChanged = true;
|
||||
});
|
||||
|
||||
removeAddon(gAddon2).then(() => {
|
||||
return getAddonActorForUrl(gClient, ADDON2_URL).then(aGrip => {
|
||||
return removeAddon(gAddon2).then(() => {
|
||||
return getAddonActorForId(gClient, ADDON2_ID).then(aGrip => {
|
||||
ok(addonListChanged, "Should be notified that list of addons changed.");
|
||||
ok(!aGrip, "Shouldn't find a addon actor for the second addon anymore.");
|
||||
});
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
* Make sure eval scripts appear in the source list
|
||||
*/
|
||||
|
||||
const ADDON_PATH = "addon-webext-contentscript.xpi";
|
||||
const TAB_URL = EXAMPLE_URL + "doc_script_webext_contentscript.html";
|
||||
|
||||
let {getExtensionUUID} = Cu.import("resource://gre/modules/Extension.jsm", {});
|
||||
|
@ -30,7 +31,7 @@ function test() {
|
|||
};
|
||||
|
||||
return Task.spawn(function* () {
|
||||
gAddon = yield addAddon(EXAMPLE_URL + "/addon-webext-contentscript.xpi");
|
||||
gAddon = yield addTemporaryAddon(ADDON_PATH);
|
||||
let uuid = getExtensionUUID(gAddon.id);
|
||||
|
||||
let options = {
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
* Check extension-added tab actor lifetimes.
|
||||
*/
|
||||
|
||||
const CHROME_URL = "chrome://mochitests/content/browser/devtools/client/debugger/test/mochitest/";
|
||||
const ACTORS_URL = CHROME_URL + "testactors.js";
|
||||
const TAB_URL = EXAMPLE_URL + "doc_empty-tab-01.html";
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
* Check extension-added tab actor lifetimes.
|
||||
*/
|
||||
|
||||
const CHROME_URL = "chrome://mochitests/content/browser/devtools/client/debugger/test/mochitest/";
|
||||
const ACTORS_URL = CHROME_URL + "testactors.js";
|
||||
const TAB_URL = EXAMPLE_URL + "doc_empty-tab-01.html";
|
||||
|
||||
|
|
|
@ -21,11 +21,15 @@ var { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm", {});
|
|||
var EventEmitter = require("devtools/shared/event-emitter");
|
||||
var { Toolbox } = require("devtools/client/framework/toolbox");
|
||||
|
||||
const chromeRegistry = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIChromeRegistry);
|
||||
|
||||
// Override promise with deprecated-sync-thenables
|
||||
promise = Cu.import("resource://devtools/shared/deprecated-sync-thenables.js", {}).Promise;
|
||||
|
||||
const EXAMPLE_URL = "http://example.com/browser/devtools/client/debugger/test/mochitest/";
|
||||
const FRAME_SCRIPT_URL = getRootDirectory(gTestPath) + "code_frame-script.js";
|
||||
const CHROME_URL = "chrome://mochitests/content/browser/devtools/client/debugger/test/mochitest/";
|
||||
const CHROME_URI = Services.io.newURI(CHROME_URL, null, null);
|
||||
|
||||
registerCleanupFunction(function* () {
|
||||
info("finish() was called, cleaning up...");
|
||||
|
@ -111,27 +115,20 @@ this.removeTab = function removeTab(aTab, aWindow) {
|
|||
return deferred.promise;
|
||||
};
|
||||
|
||||
function addAddon(aUrl) {
|
||||
info("Installing addon: " + aUrl);
|
||||
function getAddonURIFromPath(aPath) {
|
||||
let chromeURI = Services.io.newURI(aPath, null, CHROME_URI);
|
||||
return chromeRegistry.convertChromeURL(chromeURI).QueryInterface(Ci.nsIFileURL);
|
||||
}
|
||||
|
||||
let deferred = promise.defer();
|
||||
function getTemporaryAddonURLFromPath(aPath) {
|
||||
return getAddonURIFromPath(aPath).spec;
|
||||
}
|
||||
|
||||
AddonManager.getInstallForURL(aUrl, aInstaller => {
|
||||
aInstaller.install();
|
||||
let listener = {
|
||||
onInstallEnded: function (aAddon, aAddonInstall) {
|
||||
aInstaller.removeListener(listener);
|
||||
function addTemporaryAddon(aPath) {
|
||||
let addonFile = getAddonURIFromPath(aPath).file;
|
||||
info("Installing addon: " + addonFile.path);
|
||||
|
||||
// Wait for add-on's startup scripts to execute. See bug 997408
|
||||
executeSoon(function () {
|
||||
deferred.resolve(aAddonInstall);
|
||||
});
|
||||
}
|
||||
};
|
||||
aInstaller.addListener(listener);
|
||||
}, "application/x-xpinstall");
|
||||
|
||||
return deferred.promise;
|
||||
return AddonManager.installTemporaryAddon(addonFile);
|
||||
}
|
||||
|
||||
function removeAddon(aAddon) {
|
||||
|
@ -165,13 +162,13 @@ function getTabActorForUrl(aClient, aUrl) {
|
|||
return deferred.promise;
|
||||
}
|
||||
|
||||
function getAddonActorForUrl(aClient, aUrl) {
|
||||
info("Get addon actor for URL: " + aUrl);
|
||||
function getAddonActorForId(aClient, aAddonId) {
|
||||
info("Get addon actor for ID: " + aAddonId);
|
||||
let deferred = promise.defer();
|
||||
|
||||
aClient.listAddons(aResponse => {
|
||||
let addonActor = aResponse.addons.filter(aGrip => aGrip.url == aUrl).pop();
|
||||
info("got addon actor for URL: " + addonActor.actor);
|
||||
let addonActor = aResponse.addons.filter(aGrip => aGrip.id == aAddonId).pop();
|
||||
info("got addon actor for ID: " + aAddonId);
|
||||
deferred.resolve(addonActor);
|
||||
});
|
||||
|
||||
|
@ -614,9 +611,9 @@ let initDebugger = Task.async(function*(urlOrTab, options) {
|
|||
|
||||
// Creates an add-on debugger for a given add-on. The returned AddonDebugger
|
||||
// object must be destroyed before finishing the test
|
||||
function initAddonDebugger(aUrl) {
|
||||
function initAddonDebugger(aAddonId) {
|
||||
let addonDebugger = new AddonDebugger();
|
||||
return addonDebugger.init(aUrl).then(() => addonDebugger);
|
||||
return addonDebugger.init(aAddonId).then(() => addonDebugger);
|
||||
}
|
||||
|
||||
function AddonDebugger() {
|
||||
|
@ -626,7 +623,7 @@ function AddonDebugger() {
|
|||
}
|
||||
|
||||
AddonDebugger.prototype = {
|
||||
init: Task.async(function* (aUrl) {
|
||||
init: Task.async(function* (aAddonId) {
|
||||
info("Initializing an addon debugger panel.");
|
||||
|
||||
if (!DebuggerServer.initialized) {
|
||||
|
@ -645,7 +642,7 @@ AddonDebugger.prototype = {
|
|||
|
||||
yield this.client.connect();
|
||||
|
||||
let addonActor = yield getAddonActorForUrl(this.client, aUrl);
|
||||
let addonActor = yield getAddonActorForId(this.client, aAddonId);
|
||||
|
||||
let targetOptions = {
|
||||
form: addonActor,
|
||||
|
@ -951,10 +948,10 @@ function reopenVarPopup(...aArgs) {
|
|||
return hideVarPopup.apply(this, aArgs).then(() => openVarPopup.apply(this, aArgs));
|
||||
}
|
||||
|
||||
function attachAddonActorForUrl(aClient, aUrl) {
|
||||
function attachAddonActorForId(aClient, aAddonId) {
|
||||
let deferred = promise.defer();
|
||||
|
||||
getAddonActorForUrl(aClient, aUrl).then(aGrip => {
|
||||
getAddonActorForId(aClient, aAddonId).then(aGrip => {
|
||||
aClient.attachAddon(aGrip.actor, aResponse => {
|
||||
deferred.resolve([aGrip, aResponse]);
|
||||
});
|
||||
|
|
|
@ -79,7 +79,7 @@ InspectorSearch.prototype = {
|
|||
let res = yield this.walker.search(query, { reverse });
|
||||
|
||||
// Value has changed since we started this request, we're done.
|
||||
if (query != this.searchBox.value) {
|
||||
if (query !== this.searchBox.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -142,21 +142,19 @@ function SelectorAutocompleter(inspector, inputNode) {
|
|||
|
||||
this.showSuggestions = this.showSuggestions.bind(this);
|
||||
this._onSearchKeypress = this._onSearchKeypress.bind(this);
|
||||
this._onListBoxKeypress = this._onListBoxKeypress.bind(this);
|
||||
this._onSearchPopupClick = this._onSearchPopupClick.bind(this);
|
||||
this._onMarkupMutation = this._onMarkupMutation.bind(this);
|
||||
|
||||
// Options for the AutocompletePopup.
|
||||
let options = {
|
||||
panelId: "inspector-searchbox-panel",
|
||||
listBoxId: "searchbox-panel-listbox",
|
||||
listId: "searchbox-panel-listbox",
|
||||
autoSelect: true,
|
||||
position: "before_start",
|
||||
direction: "ltr",
|
||||
position: "top",
|
||||
theme: "auto",
|
||||
onClick: this._onListBoxKeypress,
|
||||
onKeypress: this._onListBoxKeypress
|
||||
onClick: this._onSearchPopupClick,
|
||||
};
|
||||
this.searchPopup = new AutocompletePopup(this.panelDoc, options);
|
||||
|
||||
this.searchPopup = new AutocompletePopup(inspector._toolbox, options);
|
||||
|
||||
this.searchBox.addEventListener("input", this.showSuggestions, true);
|
||||
this.searchBox.addEventListener("keypress", this._onSearchKeypress, true);
|
||||
|
@ -231,11 +229,11 @@ SelectorAutocompleter.prototype = {
|
|||
lastChar = secondLastChar;
|
||||
|
||||
case this.States.TAG: // eslint-disable-line
|
||||
if (lastChar == ".") {
|
||||
if (lastChar === ".") {
|
||||
this._state = this.States.CLASS;
|
||||
} else if (lastChar == "#") {
|
||||
} else if (lastChar === "#") {
|
||||
this._state = this.States.ID;
|
||||
} else if (lastChar == "[") {
|
||||
} else if (lastChar === "[") {
|
||||
this._state = this.States.ATTRIBUTE;
|
||||
} else {
|
||||
this._state = this.States.TAG;
|
||||
|
@ -246,11 +244,11 @@ SelectorAutocompleter.prototype = {
|
|||
if (subQuery.match(/[\.]+[^\.]*$/)[0].length > 2) {
|
||||
// Checks whether the subQuery has atleast one [a-zA-Z] after the
|
||||
// '.'.
|
||||
if (lastChar == " " || lastChar == ">") {
|
||||
if (lastChar === " " || lastChar === ">") {
|
||||
this._state = this.States.TAG;
|
||||
} else if (lastChar == "#") {
|
||||
} else if (lastChar === "#") {
|
||||
this._state = this.States.ID;
|
||||
} else if (lastChar == "[") {
|
||||
} else if (lastChar === "[") {
|
||||
this._state = this.States.ATTRIBUTE;
|
||||
} else {
|
||||
this._state = this.States.CLASS;
|
||||
|
@ -262,11 +260,11 @@ SelectorAutocompleter.prototype = {
|
|||
if (subQuery.match(/[#]+[^#]*$/)[0].length > 2) {
|
||||
// Checks whether the subQuery has atleast one [a-zA-Z] after the
|
||||
// '#'.
|
||||
if (lastChar == " " || lastChar == ">") {
|
||||
if (lastChar === " " || lastChar === ">") {
|
||||
this._state = this.States.TAG;
|
||||
} else if (lastChar == ".") {
|
||||
} else if (lastChar === ".") {
|
||||
this._state = this.States.CLASS;
|
||||
} else if (lastChar == "[") {
|
||||
} else if (lastChar === "[") {
|
||||
this._state = this.States.ATTRIBUTE;
|
||||
} else {
|
||||
this._state = this.States.ID;
|
||||
|
@ -275,13 +273,13 @@ SelectorAutocompleter.prototype = {
|
|||
break;
|
||||
|
||||
case this.States.ATTRIBUTE:
|
||||
if (subQuery.match(/[\[][^\]]+[\]]/) != null) {
|
||||
if (subQuery.match(/[\[][^\]]+[\]]/) !== null) {
|
||||
// Checks whether the subQuery has at least one ']' after the '['.
|
||||
if (lastChar == " " || lastChar == ">") {
|
||||
if (lastChar === " " || lastChar === ">") {
|
||||
this._state = this.States.TAG;
|
||||
} else if (lastChar == ".") {
|
||||
} else if (lastChar === ".") {
|
||||
this._state = this.States.CLASS;
|
||||
} else if (lastChar == "#") {
|
||||
} else if (lastChar === "#") {
|
||||
this._state = this.States.ID;
|
||||
} else {
|
||||
this._state = this.States.ATTRIBUTE;
|
||||
|
@ -311,20 +309,17 @@ SelectorAutocompleter.prototype = {
|
|||
* Handles keypresses inside the input box.
|
||||
*/
|
||||
_onSearchKeypress: function (event) {
|
||||
let query = this.searchBox.value;
|
||||
let popup = this.searchPopup;
|
||||
|
||||
switch (event.keyCode) {
|
||||
case event.DOM_VK_RETURN:
|
||||
case event.DOM_VK_TAB:
|
||||
if (popup.isOpen &&
|
||||
popup.getItemAtIndex(popup.itemCount - 1)
|
||||
.preLabel == query) {
|
||||
popup.selectedIndex = popup.itemCount - 1;
|
||||
this.searchBox.value = popup.selectedItem.label;
|
||||
if (popup.isOpen) {
|
||||
if (popup.selectedItem) {
|
||||
this.searchBox.value = popup.selectedItem.label;
|
||||
}
|
||||
this.hidePopup();
|
||||
} else if (!popup.isOpen &&
|
||||
event.keyCode === event.DOM_VK_TAB) {
|
||||
} else if (!popup.isOpen) {
|
||||
// When tab is pressed with focus on searchbox and closed popup,
|
||||
// do not prevent the default to avoid a keyboard trap and move focus
|
||||
// to next/previous element.
|
||||
|
@ -335,12 +330,10 @@ SelectorAutocompleter.prototype = {
|
|||
|
||||
case event.DOM_VK_UP:
|
||||
if (popup.isOpen && popup.itemCount > 0) {
|
||||
popup.focus();
|
||||
if (popup.selectedIndex == popup.itemCount - 1) {
|
||||
popup.selectedIndex =
|
||||
Math.max(0, popup.itemCount - 2);
|
||||
} else {
|
||||
if (popup.selectedIndex === 0) {
|
||||
popup.selectedIndex = popup.itemCount - 1;
|
||||
} else {
|
||||
popup.selectedIndex--;
|
||||
}
|
||||
this.searchBox.value = popup.selectedItem.label;
|
||||
}
|
||||
|
@ -348,12 +341,21 @@ SelectorAutocompleter.prototype = {
|
|||
|
||||
case event.DOM_VK_DOWN:
|
||||
if (popup.isOpen && popup.itemCount > 0) {
|
||||
popup.focus();
|
||||
popup.selectedIndex = 0;
|
||||
if (popup.selectedIndex === popup.itemCount - 1) {
|
||||
popup.selectedIndex = 0;
|
||||
} else {
|
||||
popup.selectedIndex++;
|
||||
}
|
||||
this.searchBox.value = popup.selectedItem.label;
|
||||
}
|
||||
break;
|
||||
|
||||
case event.DOM_VK_ESCAPE:
|
||||
if (popup.isOpen) {
|
||||
this.hidePopup();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
@ -364,59 +366,17 @@ SelectorAutocompleter.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Handles keypress and mouse click on the suggestions richlistbox.
|
||||
* Handles click events from the autocomplete popup.
|
||||
*/
|
||||
_onListBoxKeypress: function (event) {
|
||||
let popup = this.searchPopup;
|
||||
|
||||
switch (event.keyCode || event.button) {
|
||||
case event.DOM_VK_RETURN:
|
||||
case event.DOM_VK_TAB:
|
||||
case 0:
|
||||
// left mouse button
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
this.searchBox.value = popup.selectedItem.label;
|
||||
this.searchBox.focus();
|
||||
this.hidePopup();
|
||||
break;
|
||||
|
||||
case event.DOM_VK_UP:
|
||||
if (popup.selectedIndex == 0) {
|
||||
popup.selectedIndex = -1;
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
this.searchBox.focus();
|
||||
} else {
|
||||
let index = popup.selectedIndex;
|
||||
this.searchBox.value = popup.getItemAtIndex(index - 1).label;
|
||||
}
|
||||
break;
|
||||
|
||||
case event.DOM_VK_DOWN:
|
||||
if (popup.selectedIndex == popup.itemCount - 1) {
|
||||
popup.selectedIndex = -1;
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
this.searchBox.focus();
|
||||
} else {
|
||||
let index = popup.selectedIndex;
|
||||
this.searchBox.value = popup.getItemAtIndex(index + 1).label;
|
||||
}
|
||||
break;
|
||||
|
||||
case event.DOM_VK_BACK_SPACE:
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
this.searchBox.focus();
|
||||
if (this.searchBox.selectionStart > 0) {
|
||||
this.searchBox.value = this.searchBox.value.substring(0,
|
||||
this.searchBox.selectionStart - 1);
|
||||
}
|
||||
this.hidePopup();
|
||||
break;
|
||||
_onSearchPopupClick: function (event) {
|
||||
let selectedItem = this.searchPopup.selectedItem;
|
||||
if (selectedItem) {
|
||||
this.searchBox.value = selectedItem.label;
|
||||
}
|
||||
this.emit("processing-done");
|
||||
this.hidePopup();
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -430,6 +390,9 @@ SelectorAutocompleter.prototype = {
|
|||
|
||||
/**
|
||||
* Populates the suggestions list and show the suggestion popup.
|
||||
*
|
||||
* @return {Promise} promise that will resolve when the autocomplete popup is fully
|
||||
* displayed or hidden.
|
||||
*/
|
||||
_showPopup: function (list, firstPart, popupState) {
|
||||
let total = 0;
|
||||
|
@ -473,21 +436,24 @@ SelectorAutocompleter.prototype = {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (total > 0) {
|
||||
let onPopupOpened = this.searchPopup.once("popup-opened");
|
||||
this.searchPopup.setItems(items);
|
||||
this.searchPopup.openPopup(this.searchBox);
|
||||
} else {
|
||||
this.hidePopup();
|
||||
return onPopupOpened;
|
||||
}
|
||||
|
||||
return this.hidePopup();
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide the suggestion popup if necessary.
|
||||
*/
|
||||
hidePopup: function () {
|
||||
if (this.searchPopup.isOpen) {
|
||||
this.searchPopup.hidePopup();
|
||||
}
|
||||
let onPopupClosed = this.searchPopup.once("popup-closed");
|
||||
this.searchPopup.hidePopup();
|
||||
return onPopupClosed;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -534,7 +500,7 @@ SelectorAutocompleter.prototype = {
|
|||
if (result.query !== query) {
|
||||
// This means that this response is for a previous request and the user
|
||||
// as since typed something extra leading to a new request.
|
||||
return;
|
||||
return promise.resolve(null);
|
||||
}
|
||||
|
||||
if (state === this.States.CLASS) {
|
||||
|
@ -550,7 +516,9 @@ SelectorAutocompleter.prototype = {
|
|||
result.suggestions = [];
|
||||
}
|
||||
|
||||
this._showPopup(result.suggestions, firstPart, state);
|
||||
// Wait for the autocomplete-popup to fire its popup-opened event, to make sure
|
||||
// the autoSelect item has been selected.
|
||||
return this._showPopup(result.suggestions, firstPart, state);
|
||||
});
|
||||
|
||||
return;
|
||||
|
|
|
@ -7,26 +7,6 @@
|
|||
min-width: 250px;
|
||||
}
|
||||
|
||||
#searchbox-panel-listbox {
|
||||
width: 250px;
|
||||
max-width: 250px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
#searchbox-panel-listbox > richlistitem,
|
||||
#searchbox-panel-listbox > richlistitem[selected] {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
#searchbox-panel-listbox > richlistitem > .initial-value {
|
||||
max-width: 130px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
#searchbox-panel-listbox > richlistitem > .autocomplete-value {
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
.inspector-tabpanel > * {
|
||||
/*
|
||||
* Override `-moz-user-focus:ignore;` from toolkit/content/minimal-xul.css
|
||||
|
|
|
@ -23,7 +23,6 @@ const DRAG_DROP_MIN_INITIAL_DISTANCE = 10;
|
|||
const DRAG_DROP_HEIGHT_TO_SPEED = 500;
|
||||
const DRAG_DROP_HEIGHT_TO_SPEED_MIN = 0.5;
|
||||
const DRAG_DROP_HEIGHT_TO_SPEED_MAX = 1;
|
||||
const AUTOCOMPLETE_POPUP_PANEL_ID = "markupview_autoCompletePopup";
|
||||
const ATTR_COLLAPSE_ENABLED_PREF = "devtools.markup.collapseAttributes";
|
||||
const ATTR_COLLAPSE_LENGTH_PREF = "devtools.markup.collapseAttributeLength";
|
||||
const PREVIEW_MAX_DIM_PREF = "devtools.inspector.imagePreviewTooltipSize";
|
||||
|
@ -109,12 +108,9 @@ function MarkupView(inspector, frame, controllerWindow) {
|
|||
let options = {
|
||||
autoSelect: true,
|
||||
theme: "auto",
|
||||
// panelId option prevents the markupView autocomplete popup from
|
||||
// sharing XUL elements with other views, such as ruleView (see Bug 1191093)
|
||||
panelId: AUTOCOMPLETE_POPUP_PANEL_ID
|
||||
};
|
||||
this.popup = new AutocompletePopup(this.doc.defaultView.parent.document,
|
||||
options);
|
||||
|
||||
this.popup = new AutocompletePopup(inspector._toolbox, options);
|
||||
|
||||
this.undo = new UndoStack();
|
||||
this.undo.installController(controllerWindow);
|
||||
|
|
|
@ -120,22 +120,13 @@ function* checkData(data, editor, inspector) {
|
|||
|
||||
if (selEnd != -1) {
|
||||
is(editor.input.value, completion, "Completed value is correct");
|
||||
is(editor.input.selectionStart, selStart,
|
||||
"Selection start position is correct");
|
||||
is(editor.input.selectionStart, selStart, "Selection start position is correct");
|
||||
is(editor.input.selectionEnd, selEnd, "Selection end position is correct");
|
||||
if (popupOpen) {
|
||||
ok(editor.popup.isOpen, "Popup is open");
|
||||
} else {
|
||||
ok(editor.popup._panel.state != "open" &&
|
||||
editor.popup._panel.state != "showing",
|
||||
"Popup is closed");
|
||||
}
|
||||
is(editor.popup.isOpen, popupOpen, "Popup is " + (popupOpen ? "open" : "closed"));
|
||||
} else {
|
||||
let nodeFront = yield getNodeFront("#node14", inspector);
|
||||
let container = getContainerForNodeFront(nodeFront, inspector);
|
||||
let attr = container.editor.attrElements.get("style")
|
||||
.querySelector(".editable");
|
||||
is(attr.textContent, completion,
|
||||
"Correct value is persisted after pressing Enter");
|
||||
let attr = container.editor.attrElements.get("style").querySelector(".editable");
|
||||
is(attr.textContent, completion, "Correct value is persisted after pressing Enter");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -222,7 +222,7 @@ function CssRuleView(inspector, document, store, pageStyle) {
|
|||
autoSelect: true,
|
||||
theme: "auto"
|
||||
};
|
||||
this.popup = new AutocompletePopup(this.styleDocument, options);
|
||||
this.popup = new AutocompletePopup(inspector._toolbox, options);
|
||||
|
||||
this._showEmpty();
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ add_task(function* () {
|
|||
value: "rgb(0, 255, 0)"
|
||||
});
|
||||
|
||||
let spectrum = yield cPicker.spectrum;
|
||||
let spectrum = cPicker.spectrum;
|
||||
let onHidden = cPicker.tooltip.once("hidden");
|
||||
// Validating the color change ends up updating the rule view twice
|
||||
let onRuleViewChanged = waitForNEvents(view, "ruleview-changed", 2);
|
||||
|
|
|
@ -52,7 +52,7 @@ function* basicTest(view, name, result) {
|
|||
value: "rgb(0, 255, 0)"
|
||||
});
|
||||
|
||||
let spectrum = yield cPicker.spectrum;
|
||||
let spectrum = cPicker.spectrum;
|
||||
let onHidden = cPicker.tooltip.once("hidden");
|
||||
// Validating the color change ends up updating the rule view twice
|
||||
let onRuleViewChanged = waitForNEvents(view, "ruleview-changed", 2);
|
||||
|
|
|
@ -44,7 +44,7 @@ function* testImageTooltipAfterColorChange(swatch, url, ruleView) {
|
|||
value: 'url("chrome://global/skin/icons/warning-64.png"), linear-gradient(rgb(0, 0, 0), rgb(255, 0, 102) 400px)'
|
||||
});
|
||||
|
||||
let spectrum = yield picker.spectrum;
|
||||
let spectrum = picker.spectrum;
|
||||
let onHidden = picker.tooltip.once("hidden");
|
||||
let onModifications = ruleView.once("ruleview-changed");
|
||||
EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
|
||||
|
|
|
@ -42,7 +42,7 @@ function* testColorChangeIsntRevertedWhenOtherTooltipIsShown(ruleView) {
|
|||
value: "rgb(0, 0, 0)"
|
||||
});
|
||||
|
||||
let spectrum = yield picker.spectrum;
|
||||
let spectrum = picker.spectrum;
|
||||
|
||||
let onModifications = waitForNEvents(ruleView, "ruleview-changed", 2);
|
||||
let onHidden = picker.tooltip.once("hidden");
|
||||
|
|
|
@ -45,7 +45,7 @@ function* testPressingEnterCommitsChanges(swatch, ruleView) {
|
|||
"The text of the border css property was updated");
|
||||
|
||||
let onModified = ruleView.once("ruleview-changed");
|
||||
let spectrum = yield cPicker.spectrum;
|
||||
let spectrum = cPicker.spectrum;
|
||||
let onHidden = cPicker.tooltip.once("hidden");
|
||||
EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
|
||||
yield onHidden;
|
||||
|
|
|
@ -17,7 +17,7 @@ add_task(function* () {
|
|||
.querySelector(".ruleview-colorswatch");
|
||||
|
||||
let picker = yield openColorPickerForSwatch(cSwatch, view);
|
||||
let spectrum = yield picker.spectrum;
|
||||
let spectrum = picker.spectrum;
|
||||
let change = spectrum.once("changed");
|
||||
|
||||
info("Pressing mouse down over color picker.");
|
||||
|
|
|
@ -35,7 +35,7 @@ function* testPressingEscapeRevertsChanges(view) {
|
|||
is(propEditor.valueSpan.textContent, "#000",
|
||||
"The text of the background-color css property was updated");
|
||||
|
||||
let spectrum = yield cPicker.spectrum;
|
||||
let spectrum = cPicker.spectrum;
|
||||
|
||||
info("Pressing ESCAPE to close the tooltip");
|
||||
let onHidden = cPicker.tooltip.once("hidden");
|
||||
|
@ -76,7 +76,7 @@ function* testPressingEscapeRevertsChangesAndDisables(view) {
|
|||
is(textProp.editor.enable.style.visibility, "hidden",
|
||||
"property enable checkbox is hidden.");
|
||||
|
||||
let spectrum = yield cPicker.spectrum;
|
||||
let spectrum = cPicker.spectrum;
|
||||
|
||||
info("Pressing ESCAPE to close the tooltip");
|
||||
let onHidden = cPicker.tooltip.once("hidden");
|
||||
|
|
|
@ -85,21 +85,17 @@ function* runAutocompletionTest(toolbox, inspector, view) {
|
|||
yield selectNode("h1", inspector);
|
||||
|
||||
info("Focusing the css property editable field");
|
||||
let propertyName = view.styleDocument
|
||||
.querySelectorAll(".ruleview-propertyname")[0];
|
||||
let propertyName = view.styleDocument.querySelectorAll(".ruleview-propertyname")[0];
|
||||
let editor = yield focusEditableField(view, propertyName);
|
||||
|
||||
info("Starting to test for css property completion");
|
||||
let previousPopupSize = 0;
|
||||
for (let i = 0; i < testData.length; i++) {
|
||||
let expectPopupHiddenEvent = previousPopupSize > 0 && testData[3] === 0;
|
||||
yield testCompletion(testData[i], expectPopupHiddenEvent, editor, view);
|
||||
previousPopupSize = testData[3];
|
||||
yield testCompletion(testData[i], editor, view);
|
||||
}
|
||||
}
|
||||
|
||||
function* testCompletion([key, completion, open, selected],
|
||||
expectPopupHiddenEvent, editor, view) {
|
||||
editor, view) {
|
||||
info("Pressing key " + key);
|
||||
info("Expecting " + completion);
|
||||
info("Is popup opened: " + open);
|
||||
|
@ -117,26 +113,24 @@ function* testCompletion([key, completion, open, selected],
|
|||
onSuggest = editor.once("after-suggest");
|
||||
}
|
||||
|
||||
// Also listening for popup hiding if needed.
|
||||
let onMaybePopupHidden = expectPopupHiddenEvent
|
||||
? once(editor.popup._panel, "hidden")
|
||||
: null;
|
||||
// Also listening for popup opened/closed events if needed.
|
||||
let popupEvent = open ? "popup-opened" : "popup-closed";
|
||||
let onPopupEvent = editor.popup.isOpen !== open ? once(editor.popup, popupEvent) : null;
|
||||
|
||||
info("Synthesizing key " + key);
|
||||
EventUtils.synthesizeKey(key, {}, view.styleWindow);
|
||||
|
||||
yield onSuggest;
|
||||
yield onMaybePopupHidden;
|
||||
yield onPopupEvent;
|
||||
|
||||
info("Checking the state");
|
||||
if (completion != null) {
|
||||
if (completion !== null) {
|
||||
is(editor.input.value, completion, "Correct value is autocompleted");
|
||||
}
|
||||
if (!open) {
|
||||
ok(!(editor.popup && editor.popup.isOpen), "Popup is closed");
|
||||
} else {
|
||||
ok(editor.popup._panel.state == "open" ||
|
||||
editor.popup._panel.state == "showing", "Popup is open");
|
||||
is(editor.popup.selectedIndex != -1, selected, "An item is selected");
|
||||
ok(editor.popup.isOpen, "Popup is open");
|
||||
is(editor.popup.selectedIndex !== -1, selected, "An item is selected");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,23 +92,28 @@ function* testCompletion([key, modifiers, completion, open, selected, change],
|
|||
}
|
||||
|
||||
info("Synthesizing key " + key + ", modifiers: " + Object.keys(modifiers));
|
||||
|
||||
// Also listening for popup opened/closed events if needed.
|
||||
let popupEvent = open ? "popup-opened" : "popup-closed";
|
||||
let onPopupEvent = editor.popup.isOpen !== open ? once(editor.popup, popupEvent) : null;
|
||||
|
||||
EventUtils.synthesizeKey(key, modifiers, view.styleWindow);
|
||||
yield onDone;
|
||||
yield onPopupEvent;
|
||||
|
||||
// The key might have been a TAB or shift-TAB, in which case the editor will
|
||||
// be a new one
|
||||
editor = inplaceEditor(view.styleDocument.activeElement);
|
||||
|
||||
info("Checking the state");
|
||||
if (completion != null) {
|
||||
if (completion !== null) {
|
||||
is(editor.input.value, completion, "Correct value is autocompleted");
|
||||
}
|
||||
|
||||
if (!open) {
|
||||
ok(!(editor.popup && editor.popup.isOpen), "Popup is closed");
|
||||
} else {
|
||||
ok(editor.popup._panel.state == "open" ||
|
||||
editor.popup._panel.state == "showing", "Popup is open");
|
||||
is(editor.popup.selectedIndex != -1, selected, "An item is selected");
|
||||
ok(editor.popup.isOpen, "Popup is open");
|
||||
is(editor.popup.selectedIndex !== -1, selected, "An item is selected");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,10 +63,10 @@ function* runAutocompletionTest(toolbox, inspector, view) {
|
|||
}
|
||||
}
|
||||
|
||||
function* testCompletion([key, completion, isOpen, isSelected], editor, view) {
|
||||
function* testCompletion([key, completion, open, isSelected], editor, view) {
|
||||
info("Pressing key " + key);
|
||||
info("Expecting " + completion);
|
||||
info("Is popup opened: " + isOpen);
|
||||
info("Is popup opened: " + open);
|
||||
info("Is item selected: " + isSelected);
|
||||
|
||||
let onSuggest;
|
||||
|
@ -79,21 +79,24 @@ function* testCompletion([key, completion, isOpen, isSelected], editor, view) {
|
|||
onSuggest = editor.once("after-suggest");
|
||||
}
|
||||
|
||||
// Also listening for popup opened/closed events if needed.
|
||||
let popupEvent = open ? "popup-opened" : "popup-closed";
|
||||
let onPopupEvent = editor.popup.isOpen !== open ? once(editor.popup, popupEvent) : null;
|
||||
|
||||
info("Synthesizing key " + key);
|
||||
EventUtils.synthesizeKey(key, {}, view.styleWindow);
|
||||
|
||||
yield onSuggest;
|
||||
yield waitForTick();
|
||||
yield onPopupEvent;
|
||||
|
||||
info("Checking the state");
|
||||
if (completion != null) {
|
||||
if (completion !== null) {
|
||||
is(editor.input.value, completion, "Correct value is autocompleted");
|
||||
}
|
||||
if (!isOpen) {
|
||||
if (!open) {
|
||||
ok(!(editor.popup && editor.popup.isOpen), "Popup is closed");
|
||||
} else {
|
||||
ok(editor.popup._panel.state == "open" ||
|
||||
editor.popup._panel.state == "showing", "Popup is open");
|
||||
is(editor.popup.selectedIndex != -1, isSelected, "An item is selected");
|
||||
ok(editor.popup.isOpen, "Popup is open");
|
||||
is(editor.popup.selectedIndex !== -1, isSelected, "An item is selected");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,12 +100,17 @@ function* testCompletion([key, modifiers, completion, open, selected, change],
|
|||
: null;
|
||||
}
|
||||
|
||||
// Also listening for popup opened/closed events if needed.
|
||||
let popupEvent = open ? "popup-opened" : "popup-closed";
|
||||
let onPopupEvent = editor.popup.isOpen !== open ? once(editor.popup, popupEvent) : null;
|
||||
|
||||
info("Synthesizing key " + key + ", modifiers: " + Object.keys(modifiers));
|
||||
EventUtils.synthesizeKey(key, modifiers, view.styleWindow);
|
||||
yield onDone;
|
||||
yield onPopupEvent;
|
||||
|
||||
info("Checking the state");
|
||||
if (completion != null) {
|
||||
if (completion !== null) {
|
||||
// The key might have been a TAB or shift-TAB, in which case the editor will
|
||||
// be a new one
|
||||
editor = inplaceEditor(view.styleDocument.activeElement);
|
||||
|
@ -114,8 +119,7 @@ function* testCompletion([key, modifiers, completion, open, selected, change],
|
|||
if (!open) {
|
||||
ok(!(editor.popup && editor.popup.isOpen), "Popup is closed");
|
||||
} else {
|
||||
ok(editor.popup._panel.state == "open" ||
|
||||
editor.popup._panel.state == "showing", "Popup is open");
|
||||
is(editor.popup.selectedIndex != -1, selected, "An item is selected");
|
||||
ok(editor.popup.isOpen, "Popup is open");
|
||||
is(editor.popup.selectedIndex !== -1, selected, "An item is selected");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ function* runAutocompletionTest(toolbox, inspector, view) {
|
|||
editor.popup.selectedIndex = itemIndex;
|
||||
|
||||
let node = editor.popup._list.childNodes[itemIndex];
|
||||
EventUtils.synthesizeMouseAtCenter(node, {}, view.styleWindow);
|
||||
EventUtils.synthesizeMouseAtCenter(node, {}, editor.popup._window);
|
||||
|
||||
is(editor.input.value, "background-color", "Correct value is autocompleted");
|
||||
}
|
||||
|
|
|
@ -39,8 +39,8 @@ add_task(function* () {
|
|||
|
||||
info("Select the background-color suggestion with a mouse click.");
|
||||
let onSuggest = editor.once("after-suggest");
|
||||
let node = editor.popup._list.childNodes[itemIndex];
|
||||
EventUtils.synthesizeMouseAtCenter(node, {}, view.styleWindow);
|
||||
let node = editor.popup.elements.get(bgcItem);
|
||||
EventUtils.synthesizeMouseAtCenter(node, {}, editor.popup._window);
|
||||
yield onSuggest;
|
||||
is(editor.input.value, "background-color", "Correct value is autocompleted");
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ add_task(function* () {
|
|||
|
||||
info("Check that UP/DOWN navigates in the input, even when next to a number");
|
||||
EventUtils.synthesizeKey("VK_DOWN", {}, view.styleWindow);
|
||||
ok(editor.input.selectionStart != pos, "Input caret moved");
|
||||
ok(editor.input.selectionStart !== pos, "Input caret moved");
|
||||
is(editor.input.value, LONG_CSS_VALUE, "Input value was not decremented.");
|
||||
|
||||
info("Move the caret to the end of the gradient definition.");
|
||||
|
@ -95,8 +95,10 @@ add_task(function* () {
|
|||
info("Select the background-color suggestion with a mouse click.");
|
||||
let onRuleviewChanged = view.once("ruleview-changed");
|
||||
let onSuggest = editor.once("after-suggest");
|
||||
|
||||
let node = editor.popup._list.childNodes[editor.popup.selectedIndex];
|
||||
EventUtils.synthesizeMouseAtCenter(node, {}, view.styleWindow);
|
||||
EventUtils.synthesizeMouseAtCenter(node, {}, editor.popup._window);
|
||||
|
||||
yield onSuggest;
|
||||
yield onRuleviewChanged;
|
||||
|
||||
|
|
|
@ -24,11 +24,13 @@ add_task(function* () {
|
|||
|
||||
info("Pressing key VK_DOWN");
|
||||
let onSuggest = once(editor.input, "keypress");
|
||||
let onPopupOpened = once(editor.popup, "popup-opened");
|
||||
|
||||
EventUtils.synthesizeKey("VK_DOWN", {}, view.styleWindow);
|
||||
|
||||
info("Waiting for autocomplete popup to be displayed");
|
||||
yield onSuggest;
|
||||
yield waitForTick();
|
||||
yield onPopupOpened;
|
||||
|
||||
ok(view.popup && view.popup.isOpen, "Popup should be opened");
|
||||
|
||||
|
|
|
@ -64,6 +64,6 @@ add_task(function* () {
|
|||
ok(!inplaceEditor(propEditor.valueSpan),
|
||||
"The inplace editor wasn't shown as a result of the color swatch click");
|
||||
|
||||
let spectrum = yield colorPicker.spectrum;
|
||||
let spectrum = colorPicker.spectrum;
|
||||
is(spectrum.rgb, "200,170,140,0.5", "The correct color picker was shown");
|
||||
});
|
||||
|
|
|
@ -61,7 +61,7 @@ add_task(function* () {
|
|||
let dropper = yield openEyedropper(view, swatch);
|
||||
|
||||
let tooltip = view.tooltips.colorPicker.tooltip;
|
||||
ok(tooltip.isHidden(),
|
||||
ok(!tooltip.isVisible(),
|
||||
"color picker tooltip is closed after opening eyedropper");
|
||||
|
||||
yield testESC(swatch, dropper);
|
||||
|
@ -134,8 +134,7 @@ function openEyedropper(view, swatch) {
|
|||
let tooltip = view.tooltips.colorPicker.tooltip;
|
||||
|
||||
tooltip.once("shown", () => {
|
||||
let tooltipDoc = tooltip.content.contentDocument;
|
||||
let dropperButton = tooltipDoc.querySelector("#eyedropper-button");
|
||||
let dropperButton = tooltip.doc.querySelector("#eyedropper-button");
|
||||
|
||||
tooltip.once("eyedropper-opened", (event, dropper) => {
|
||||
deferred.resolve(dropper);
|
||||
|
|
|
@ -28,6 +28,5 @@ add_task(function* () {
|
|||
ok(!inplaceEditor(swatch.parentNode),
|
||||
"The inplace editor wasn't shown as a result of the filter swatch click");
|
||||
|
||||
yield filterTooltip.widget;
|
||||
yield hideTooltipAndWaitForRuleViewChanged(filterTooltip, view);
|
||||
});
|
||||
|
|
|
@ -25,7 +25,7 @@ add_task(function* () {
|
|||
|
||||
info("Get the cssfilter widget instance");
|
||||
let filterTooltip = view.tooltips.filterEditor;
|
||||
let widget = yield filterTooltip.widget;
|
||||
let widget = filterTooltip.widget;
|
||||
|
||||
info("Set a new value in the cssfilter widget");
|
||||
onRuleViewChanged = view.once("ruleview-changed");
|
||||
|
|
|
@ -38,7 +38,6 @@ function* testPressingEscapeRevertsChanges(view) {
|
|||
function* testPressingEscapeRevertsChangesAndDisables(view) {
|
||||
let ruleEditor = getRuleViewRuleEditor(view, 1);
|
||||
let propEditor = ruleEditor.rule.textProps[0].editor;
|
||||
let swatch = propEditor.valueSpan.querySelector(".ruleview-filterswatch");
|
||||
|
||||
info("Disabling filter property");
|
||||
let onRuleViewChanged = view.once("ruleview-changed");
|
||||
|
@ -56,6 +55,7 @@ function* testPressingEscapeRevertsChangesAndDisables(view) {
|
|||
let newValue = yield getRulePropertyValue("filter");
|
||||
is(newValue, "", "filter should have been unset.");
|
||||
|
||||
let swatch = propEditor.valueSpan.querySelector(".ruleview-filterswatch");
|
||||
yield clickOnFilterSwatch(swatch, view);
|
||||
|
||||
ok(!propEditor.element.classList.contains("ruleview-overridden"),
|
||||
|
@ -103,9 +103,8 @@ function* setValueInFilterWidget(value, view) {
|
|||
info("Setting the CSS filter value in the tooltip");
|
||||
|
||||
let filterTooltip = view.tooltips.filterEditor;
|
||||
let widget = yield filterTooltip.widget;
|
||||
let onRuleViewChanged = view.once("ruleview-changed");
|
||||
widget.setCssValue(value);
|
||||
filterTooltip.widget.setCssValue(value);
|
||||
yield onRuleViewChanged;
|
||||
}
|
||||
|
||||
|
@ -113,8 +112,7 @@ function* pressEscapeToCloseTooltip(view) {
|
|||
info("Pressing ESCAPE to close the tooltip");
|
||||
|
||||
let filterTooltip = view.tooltips.filterEditor;
|
||||
let widget = yield filterTooltip.widget;
|
||||
let onRuleViewChanged = view.once("ruleview-changed");
|
||||
EventUtils.sendKey("ESCAPE", widget.styleWindow);
|
||||
EventUtils.sendKey("ESCAPE", filterTooltip.widget.styleWindow);
|
||||
yield onRuleViewChanged;
|
||||
}
|
||||
|
|
|
@ -358,9 +358,14 @@ function getRuleViewSelectorHighlighterIcon(view, selectorText) {
|
|||
*/
|
||||
var simulateColorPickerChange = Task.async(function* (ruleView, colorPicker,
|
||||
newRgba, expectedChange) {
|
||||
let onComputedStyleChanged;
|
||||
if (expectedChange) {
|
||||
let {selector, name, value} = expectedChange;
|
||||
onComputedStyleChanged = waitForComputedStyleProperty(selector, null, name, value);
|
||||
}
|
||||
let onRuleViewChanged = ruleView.once("ruleview-changed");
|
||||
info("Getting the spectrum colorpicker object");
|
||||
let spectrum = yield colorPicker.spectrum;
|
||||
let spectrum = colorPicker.spectrum;
|
||||
info("Setting the new color");
|
||||
spectrum.rgb = newRgba;
|
||||
info("Applying the change");
|
||||
|
@ -371,8 +376,7 @@ var simulateColorPickerChange = Task.async(function* (ruleView, colorPicker,
|
|||
|
||||
if (expectedChange) {
|
||||
info("Waiting for the style to be applied on the page");
|
||||
let {selector, name, value} = expectedChange;
|
||||
yield waitForComputedStyleProperty(selector, null, name, value);
|
||||
yield onComputedStyleChanged;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -261,10 +261,10 @@ exports.TooltipsOverlay = TooltipsOverlay;
|
|||
|
||||
TooltipsOverlay.prototype = {
|
||||
get isEditing() {
|
||||
return this.colorPicker.tooltip.isShown() ||
|
||||
return this.colorPicker.tooltip.isVisible() ||
|
||||
this.colorPicker.eyedropperOpen ||
|
||||
this.cubicBezier.tooltip.isShown() ||
|
||||
this.filterEditor.tooltip.isShown();
|
||||
this.cubicBezier.tooltip.isVisible() ||
|
||||
this.filterEditor.tooltip.isVisible();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -290,11 +290,12 @@ TooltipsOverlay.prototype = {
|
|||
|
||||
if (this.isRuleView) {
|
||||
// Color picker tooltip
|
||||
this.colorPicker = new SwatchColorPickerTooltip(panelDoc);
|
||||
let { toolbox } = this.view.inspector;
|
||||
this.colorPicker = new SwatchColorPickerTooltip(toolbox);
|
||||
// Cubic bezier tooltip
|
||||
this.cubicBezier = new SwatchCubicBezierTooltip(panelDoc);
|
||||
this.cubicBezier = new SwatchCubicBezierTooltip(toolbox);
|
||||
// Filter editor tooltip
|
||||
this.filterEditor = new SwatchFilterTooltip(panelDoc);
|
||||
this.filterEditor = new SwatchFilterTooltip(toolbox);
|
||||
}
|
||||
|
||||
this._isStarted = true;
|
||||
|
@ -381,12 +382,12 @@ TooltipsOverlay.prototype = {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (this.isRuleView && this.colorPicker.tooltip.isShown()) {
|
||||
if (this.isRuleView && this.colorPicker.tooltip.isVisible()) {
|
||||
this.colorPicker.revert();
|
||||
this.colorPicker.hide();
|
||||
}
|
||||
|
||||
if (this.isRuleView && this.cubicBezier.tooltip.isShown()) {
|
||||
if (this.isRuleView && this.cubicBezier.tooltip.isVisible()) {
|
||||
this.cubicBezier.revert();
|
||||
this.cubicBezier.hide();
|
||||
}
|
||||
|
@ -395,7 +396,7 @@ TooltipsOverlay.prototype = {
|
|||
this.cssDocs.hide();
|
||||
}
|
||||
|
||||
if (this.isRuleView && this.filterEditor.tooltip.isShown()) {
|
||||
if (this.isRuleView && this.filterEditor.tooltip.isVisible()) {
|
||||
this.filterEditor.revert();
|
||||
this.filterEdtior.hide();
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ skip-if = e10s # Bug 1111546 (e10s)
|
|||
[browser_styleinspector_tooltip-multiple-background-images.js]
|
||||
[browser_styleinspector_tooltip-shorthand-fontfamily.js]
|
||||
[browser_styleinspector_tooltip-size.js]
|
||||
skip-if = e10s || os == 'linux' # Bug 1111546 (e10s), bug 1093431 (linux)
|
||||
[browser_styleinspector_transform-highlighter-01.js]
|
||||
[browser_styleinspector_transform-highlighter-02.js]
|
||||
[browser_styleinspector_transform-highlighter-03.js]
|
||||
|
|
|
@ -70,12 +70,13 @@ function* testPickerDimension(ruleView) {
|
|||
|
||||
// The colorpicker spectrum's iframe has a fixed width height, so let's
|
||||
// make sure the tooltip is at least as big as that
|
||||
let w = cPicker.tooltip.panel.querySelector("iframe").width;
|
||||
let h = cPicker.tooltip.panel.querySelector("iframe").height;
|
||||
let panelRect = cPicker.tooltip.panel.getBoundingClientRect();
|
||||
let spectrumRect = cPicker.spectrum.element.getBoundingClientRect();
|
||||
let panelRect = cPicker.tooltip.container.getBoundingClientRect();
|
||||
|
||||
ok(panelRect.width >= w, "The panel is wide enough to show the picker");
|
||||
ok(panelRect.height >= h, "The panel is high enough to show the picker");
|
||||
ok(panelRect.width >= spectrumRect.width,
|
||||
"The panel is wide enough to show the picker");
|
||||
ok(panelRect.height >= spectrumRect.height,
|
||||
"The panel is high enough to show the picker");
|
||||
|
||||
let onHidden = cPicker.tooltip.once("hidden");
|
||||
let onRuleViewChanged = ruleView.once("ruleview-changed");
|
||||
|
|
|
@ -14,11 +14,11 @@ const KEY_STATES = [
|
|||
[".", "div."],
|
||||
["VK_UP", "div.c1"],
|
||||
["VK_DOWN", "div.l1"],
|
||||
["VK_DOWN", "div.l1"],
|
||||
["VK_BACK_SPACE", "div.l"],
|
||||
["VK_TAB", "div.l1"],
|
||||
[" ", "div.l1 "],
|
||||
["VK_UP", "div.l1 div"],
|
||||
["VK_UP", "div.l1 span"],
|
||||
["VK_UP", "div.l1 div"],
|
||||
[".", "div.l1 div."],
|
||||
["VK_TAB", "div.l1 div.c1"],
|
||||
|
@ -33,6 +33,7 @@ const KEY_STATES = [
|
|||
["VK_BACK_SPACE", "div.l1 d"],
|
||||
["VK_BACK_SPACE", "div.l1 "],
|
||||
["VK_UP", "div.l1 div"],
|
||||
["VK_UP", "div.l1 span"],
|
||||
["VK_UP", "div.l1 div"],
|
||||
["VK_TAB", "div.l1 div"],
|
||||
["VK_BACK_SPACE", "div.l1 di"],
|
||||
|
@ -40,7 +41,6 @@ const KEY_STATES = [
|
|||
["VK_BACK_SPACE", "div.l1 "],
|
||||
["VK_DOWN", "div.l1 div"],
|
||||
["VK_DOWN", "div.l1 span"],
|
||||
["VK_DOWN", "div.l1 span"],
|
||||
["VK_BACK_SPACE", "div.l1 spa"],
|
||||
["VK_BACK_SPACE", "div.l1 sp"],
|
||||
["VK_BACK_SPACE", "div.l1 s"],
|
||||
|
@ -68,6 +68,9 @@ add_task(function* () {
|
|||
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
|
||||
yield done;
|
||||
|
||||
is(inspector.searchBox.value, query, "The searchbox value is correct.");
|
||||
info("Waiting for search query to complete");
|
||||
yield inspector.searchSuggestions._lastQuery;
|
||||
|
||||
is(inspector.searchBox.value, query, "The searchbox value is correct");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -127,13 +127,11 @@ devtools.jar:
|
|||
content/framework/connect/connect.css (framework/connect/connect.css)
|
||||
content/framework/connect/connect.js (framework/connect/connect.js)
|
||||
content/shared/widgets/graphs-frame.xhtml (shared/widgets/graphs-frame.xhtml)
|
||||
content/shared/widgets/spectrum-frame.xhtml (shared/widgets/spectrum-frame.xhtml)
|
||||
content/shared/widgets/cubic-bezier-frame.xhtml (shared/widgets/cubic-bezier-frame.xhtml)
|
||||
content/shared/widgets/cubic-bezier.css (shared/widgets/cubic-bezier.css)
|
||||
content/shared/widgets/mdn-docs-frame.xhtml (shared/widgets/mdn-docs-frame.xhtml)
|
||||
content/shared/widgets/mdn-docs.css (shared/widgets/mdn-docs.css)
|
||||
content/shared/widgets/filter-frame.xhtml (shared/widgets/filter-frame.xhtml)
|
||||
content/shared/widgets/filter-widget.css (shared/widgets/filter-widget.css)
|
||||
content/shared/widgets/spectrum.css (shared/widgets/spectrum.css)
|
||||
content/eyedropper/eyedropper.xul (eyedropper/eyedropper.xul)
|
||||
content/eyedropper/crosshairs.css (eyedropper/crosshairs.css)
|
||||
content/eyedropper/nocursor.css (eyedropper/nocursor.css)
|
||||
|
@ -195,7 +193,6 @@ devtools.jar:
|
|||
skin/images/breadcrumbs-scrollbutton.png (themes/images/breadcrumbs-scrollbutton.png)
|
||||
skin/images/breadcrumbs-scrollbutton@2x.png (themes/images/breadcrumbs-scrollbutton@2x.png)
|
||||
skin/animationinspector.css (themes/animationinspector.css)
|
||||
skin/spectrum.css (themes/spectrum.css)
|
||||
skin/eyedropper.css (themes/eyedropper.css)
|
||||
skin/canvasdebugger.css (themes/canvasdebugger.css)
|
||||
skin/debugger.css (themes/debugger.css)
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!-- LOCALIZATION NOTE : FILE These strings are used in the CSS Filter Editor Widget
|
||||
- which can be found in a tooltip that appears in the Rule View when clicking
|
||||
- on a filter swatch displayed next to CSS declarations like 'filter: blur(2px)'. -->
|
||||
|
||||
<!-- LOCALIZATION NOTE (filterListSelectPlaceholder): This string is used as
|
||||
- a preview option in the list of possible filters <select> -->
|
||||
<!ENTITY filterListSelectPlaceholder "Select a Filter">
|
||||
|
||||
<!-- LOCALIZATION NOTE (addNewFilterButton): This string is displayed on a button used to add new filters -->
|
||||
<!ENTITY addNewFilterButton "Add">
|
||||
|
||||
<!-- LOCALIZATION NOTE (newPresetPlaceholder): This string is used as
|
||||
- a placeholder in the list of presets which is used to save a new preset -->
|
||||
<!ENTITY newPresetPlaceholder "Preset Name">
|
||||
|
||||
<!-- LOCALIZATION NOTE (savePresetButton): This string is displayed on a button used to save a new preset -->
|
||||
<!ENTITY savePresetButton "Save">
|
||||
|
||||
<!-- LOCALIZATION NOTE(presetsToggleButton): This string is used in a button which toggles the presets list -->
|
||||
<!ENTITY presetsToggleButton "Presets">
|
|
@ -37,3 +37,25 @@ dragHandleTooltipText=Drag up or down to re-order filter
|
|||
# filters' labels which can be dragged left/right to increase/decrease
|
||||
# the filter's value (like photoshop)
|
||||
labelDragTooltipText=Drag left or right to decrease or increase the value
|
||||
|
||||
# LOCALIZATION NOTE (filterListSelectPlaceholder):
|
||||
# This string is used as a preview option in the list of possible filters
|
||||
# <select>
|
||||
filterListSelectPlaceholder=Select a Filter
|
||||
|
||||
# LOCALIZATION NOTE (addNewFilterButton):
|
||||
# This string is displayed on a button used to add new filters
|
||||
addNewFilterButton=Add
|
||||
|
||||
# LOCALIZATION NOTE (newPresetPlaceholder):
|
||||
# This string is used as a placeholder in the list of presets which is used to
|
||||
# save a new preset
|
||||
newPresetPlaceholder=Preset Name
|
||||
|
||||
# LOCALIZATION NOTE (savePresetButton):
|
||||
# This string is displayed on a button used to save a new preset
|
||||
savePresetButton=Save
|
||||
|
||||
# LOCALIZATION NOTE(presetsToggleButton):
|
||||
# This string is used in a button which toggles the presets list
|
||||
presetsToggleButton=Presets
|
||||
|
|
|
@ -97,6 +97,7 @@ skip-if = (os == 'linux' && e10s && debug) # Bug 1242204
|
|||
[browser_net_json_text_mime.js]
|
||||
[browser_net_jsonp.js]
|
||||
[browser_net_large-response.js]
|
||||
[browser_net_leak_on_tab_close.js]
|
||||
[browser_net_open_request_in_tab.js]
|
||||
[browser_net_page-nav.js]
|
||||
[browser_net_pane-collapse.js]
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Tests that netmonitor doesn't leak windows on parent-side pages (bug 1285638)
|
||||
*/
|
||||
|
||||
add_task(function* () {
|
||||
// Tell initNetMonitor to enable cache. Otherwise it will assert that there were more
|
||||
// than zero network requests during the page load. But when loading about:config,
|
||||
// there are none.
|
||||
let [,, monitor] = yield initNetMonitor("about:config", null, true);
|
||||
ok(monitor, "The network monitor was opened");
|
||||
yield teardown(monitor);
|
||||
finish();
|
||||
});
|
|
@ -5,135 +5,106 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const Services = require("Services");
|
||||
const {gDevTools} = require("devtools/client/framework/devtools");
|
||||
const events = require("devtools/shared/event-emitter");
|
||||
const {HTMLTooltip} = require("devtools/client/shared/widgets/HTMLTooltip");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
||||
let itemIdCounter = 0;
|
||||
/**
|
||||
* Autocomplete popup UI implementation.
|
||||
*
|
||||
* @constructor
|
||||
* @param {nsIDOMDocument} document
|
||||
* The document you want the popup attached to.
|
||||
* @param {Toolbox} toolbox
|
||||
* The devtools toolbox required to instanciate the HTMLTooltip.
|
||||
* @param {Object} options
|
||||
* 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.
|
||||
* - listId {String} The id for the list <LI> element.
|
||||
* - position {String} The position for the tooltip ("top" or "bottom").
|
||||
* - 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.
|
||||
* - direction {String} The direction of the text in the panel. rtl / 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 richlistitems.
|
||||
* panel to be automatically selected when the popup shows.
|
||||
* - onSelect {String} Callback called when the selected index is updated.
|
||||
* - onClick {String} Callback called when the autocomplete popup receives a click
|
||||
* event. The selectedIndex will already be updated if need be.
|
||||
*/
|
||||
function AutocompletePopup(document, options = {}) {
|
||||
this._document = document;
|
||||
function AutocompletePopup(toolbox, options = {}) {
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
this._document = toolbox.doc;
|
||||
|
||||
this.autoSelect = options.autoSelect || false;
|
||||
this.position = options.position || "after_start";
|
||||
this.direction = options.direction || "ltr";
|
||||
this.position = options.position || "bottom";
|
||||
let theme = options.theme || "dark";
|
||||
|
||||
this.onSelectCallback = options.onSelect;
|
||||
this.onClickCallback = options.onClick;
|
||||
this.onKeypressCallback = options.onKeypress;
|
||||
|
||||
let id = options.panelId || "devtools_autoCompletePopup";
|
||||
let theme = options.theme || "dark";
|
||||
// If theme is auto, use the devtools.theme pref
|
||||
if (theme == "auto") {
|
||||
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) {
|
||||
this._panel = this._document.createElementNS(XUL_NS, "panel");
|
||||
this._panel.setAttribute("id", id);
|
||||
this._panel.className = "devtools-autocomplete-popup devtools-monospace "
|
||||
+ theme + "-theme";
|
||||
|
||||
this._panel.setAttribute("noautofocus", "true");
|
||||
this._panel.setAttribute("level", "top");
|
||||
if (!options.onKeypress) {
|
||||
this._panel.setAttribute("ignorekeys", "true");
|
||||
}
|
||||
// Stop this appearing as an alert to accessibility.
|
||||
this._panel.setAttribute("role", "presentation");
|
||||
|
||||
let mainPopupSet = this._document.getElementById("mainPopupSet");
|
||||
if (mainPopupSet) {
|
||||
mainPopupSet.appendChild(this._panel);
|
||||
} else {
|
||||
this._document.documentElement.appendChild(this._panel);
|
||||
}
|
||||
} else {
|
||||
this._list = this._panel.firstChild;
|
||||
}
|
||||
|
||||
if (!this._list) {
|
||||
this._list = this._document.createElementNS(XUL_NS, "richlistbox");
|
||||
this._panel.appendChild(this._list);
|
||||
|
||||
// Open and hide the panel, so we initialize the API of the richlistbox.
|
||||
this._panel.openPopup(null, this.position, 0, 0);
|
||||
this._panel.hidePopup();
|
||||
}
|
||||
// Create HTMLTooltip instance
|
||||
this._tooltip = new HTMLTooltip(toolbox);
|
||||
this._tooltip.panel.classList.add(
|
||||
"devtools-autocomplete-popup",
|
||||
"devtools-monospace",
|
||||
theme + "-theme");
|
||||
// Stop this appearing as an alert to accessibility.
|
||||
this._tooltip.panel.setAttribute("role", "presentation");
|
||||
|
||||
this._list = this._document.createElementNS(HTML_NS, "ul");
|
||||
this._list.setAttribute("flex", "1");
|
||||
this._list.setAttribute("seltype", "single");
|
||||
|
||||
if (options.listBoxId) {
|
||||
this._list.setAttribute("id", options.listBoxId);
|
||||
if (options.listId) {
|
||||
this._list.setAttribute("id", options.listId);
|
||||
}
|
||||
this._list.className = "devtools-autocomplete-listbox " + theme + "-theme";
|
||||
|
||||
this.onSelect = this.onSelect.bind(this);
|
||||
this._tooltip.setContent(this._list);
|
||||
|
||||
this.onClick = this.onClick.bind(this);
|
||||
this.onKeypress = this.onKeypress.bind(this);
|
||||
this._list.addEventListener("select", this.onSelect, false);
|
||||
this._list.addEventListener("click", this.onClick, false);
|
||||
this._list.addEventListener("keypress", this.onKeypress, false);
|
||||
|
||||
this._itemIdCounter = 0;
|
||||
// Array of raw autocomplete items
|
||||
this.items = [];
|
||||
// Map of autocompleteItem to HTMLElement
|
||||
this.elements = new WeakMap();
|
||||
|
||||
events.decorate(this);
|
||||
this.selectedIndex = -1;
|
||||
}
|
||||
exports.AutocompletePopup = AutocompletePopup;
|
||||
|
||||
AutocompletePopup.prototype = {
|
||||
_document: null,
|
||||
_panel: null,
|
||||
_tooltip: null,
|
||||
_list: null,
|
||||
__scrollbarWidth: null,
|
||||
|
||||
// Event handlers.
|
||||
onSelect: function (e) {
|
||||
this.emit("popup-select");
|
||||
if (this.onSelectCallback) {
|
||||
this.onSelectCallback(e);
|
||||
}
|
||||
},
|
||||
|
||||
onClick: function (e) {
|
||||
let item = e.target.closest(".autocomplete-item");
|
||||
if (item && typeof item.dataset.index !== "undefined") {
|
||||
this.selectedIndex = parseInt(item.dataset.index, 10);
|
||||
}
|
||||
|
||||
this.emit("popup-click");
|
||||
if (this.onClickCallback) {
|
||||
this.onClickCallback(e);
|
||||
}
|
||||
},
|
||||
|
||||
onKeypress: function (e) {
|
||||
this.emit("popup-keypress");
|
||||
if (this.onKeypressCallback) {
|
||||
this.onKeypressCallback(e);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Open the autocomplete popup panel.
|
||||
*
|
||||
|
@ -151,13 +122,19 @@ AutocompletePopup.prototype = {
|
|||
openPopup: function (anchor, xOffset = 0, yOffset = 0, index) {
|
||||
this.__maxLabelLength = -1;
|
||||
this._updateSize();
|
||||
this._panel.openPopup(anchor, this.position, xOffset, yOffset);
|
||||
this._tooltip.show(anchor, {
|
||||
x: xOffset,
|
||||
y: yOffset,
|
||||
position: this.position,
|
||||
});
|
||||
|
||||
if (this.autoSelect) {
|
||||
this.selectItemAtIndex(index);
|
||||
}
|
||||
this._tooltip.once("shown", () => {
|
||||
if (this.autoSelect) {
|
||||
this.selectItemAtIndex(index);
|
||||
}
|
||||
|
||||
this.emit("popup-opened");
|
||||
this.emit("popup-opened");
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -167,30 +144,29 @@ AutocompletePopup.prototype = {
|
|||
* The position of the item to select.
|
||||
*/
|
||||
selectItemAtIndex: function (index) {
|
||||
if (typeof index != "number") {
|
||||
if (typeof index !== "number") {
|
||||
// If no index was provided, select the item closest to the input.
|
||||
let isAboveInput = this.position.includes("before");
|
||||
let isAboveInput = this.position === "top";
|
||||
index = isAboveInput ? this.itemCount - 1 : 0;
|
||||
}
|
||||
this.selectedIndex = index;
|
||||
this._list.ensureIndexIsVisible(this._list.selectedIndex);
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide the autocomplete popup panel.
|
||||
*/
|
||||
hidePopup: function () {
|
||||
// Return accessibility focus to the input.
|
||||
this._document.activeElement.removeAttribute("aria-activedescendant");
|
||||
this._panel.hidePopup();
|
||||
this._tooltip.once("hidden", () => {
|
||||
this.emit("popup-closed");
|
||||
});
|
||||
this._tooltip.hide();
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if the autocomplete popup is open.
|
||||
*/
|
||||
get isOpen() {
|
||||
return this._panel &&
|
||||
(this._panel.state == "open" || this._panel.state == "showing");
|
||||
return this._tooltip && this._tooltip.isVisible();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -204,19 +180,17 @@ AutocompletePopup.prototype = {
|
|||
this.hidePopup();
|
||||
}
|
||||
|
||||
this._list.removeEventListener("select", this.onSelect, false);
|
||||
this._list.removeEventListener("click", this.onClick, false);
|
||||
this._list.removeEventListener("keypress", this.onKeypress, false);
|
||||
|
||||
if (this.autoThemeEnabled) {
|
||||
gDevTools.off("pref-changed", this._handleThemeChange);
|
||||
}
|
||||
|
||||
this._list.remove();
|
||||
this._panel.remove();
|
||||
this._tooltip.destroy();
|
||||
this._document = null;
|
||||
this._list = null;
|
||||
this._panel = null;
|
||||
this._tooltip = null;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -228,7 +202,7 @@ AutocompletePopup.prototype = {
|
|||
* @return {Object} The autocomplete item at index index.
|
||||
*/
|
||||
getItemAtIndex: function (index) {
|
||||
return this._list.getItemAtIndex(index)._autocompleteItem;
|
||||
return this.items[index];
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -237,13 +211,8 @@ AutocompletePopup.prototype = {
|
|||
* @return {Array} The array of autocomplete items.
|
||||
*/
|
||||
getItems: function () {
|
||||
let items = [];
|
||||
|
||||
Array.forEach(this._list.childNodes, function (item) {
|
||||
items.push(item._autocompleteItem);
|
||||
});
|
||||
|
||||
return items;
|
||||
// Return a copy of the array to avoid side effects from the caller code.
|
||||
return this.items.slice(0);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -258,30 +227,24 @@ AutocompletePopup.prototype = {
|
|||
this.clearItems();
|
||||
items.forEach(this.appendItem, this);
|
||||
|
||||
// Make sure that the new content is properly fitted by the XUL richlistbox.
|
||||
if (this.isOpen) {
|
||||
if (this.autoSelect) {
|
||||
this.selectItemAtIndex(index);
|
||||
}
|
||||
this._updateSize();
|
||||
if (this.isOpen && this.autoSelect) {
|
||||
this.selectItemAtIndex(index);
|
||||
}
|
||||
},
|
||||
|
||||
__maxLabelLength: -1,
|
||||
|
||||
get _maxLabelLength() {
|
||||
if (this.__maxLabelLength != -1) {
|
||||
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 + "");
|
||||
for (let {label, count} of this.items) {
|
||||
if (count) {
|
||||
label += count + "";
|
||||
}
|
||||
max = Math.max(str.length, max);
|
||||
max = Math.max(label.length, max);
|
||||
}
|
||||
|
||||
this.__maxLabelLength = max;
|
||||
|
@ -292,26 +255,32 @@ AutocompletePopup.prototype = {
|
|||
* Update the panel size to fit the content.
|
||||
*/
|
||||
_updateSize: function () {
|
||||
if (!this._panel) {
|
||||
if (!this._tooltip) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._list.style.width = (this._maxLabelLength + 3) + "ch";
|
||||
this._list.ensureIndexIsVisible(this._list.selectedIndex);
|
||||
let selectedItem = this.selectedItem;
|
||||
if (selectedItem) {
|
||||
this._scrollElementIntoViewIfNeeded(this.elements.get(selectedItem));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update accessibility appropriately when the selected item is changed.
|
||||
*/
|
||||
_updateAriaActiveDescendant: function () {
|
||||
if (!this._list.selectedItem) {
|
||||
// Return accessibility focus to the input.
|
||||
this._document.activeElement.removeAttribute("aria-activedescendant");
|
||||
_scrollElementIntoViewIfNeeded: function (element) {
|
||||
let quads = element.getBoxQuads({relativeTo: this._tooltip.panel});
|
||||
if (!quads || !quads[0]) {
|
||||
return;
|
||||
}
|
||||
// Focus this for accessibility so users know about the selected item.
|
||||
this._document.activeElement.setAttribute("aria-activedescendant",
|
||||
this._list.selectedItem.id);
|
||||
|
||||
let {top, height} = quads[0].bounds;
|
||||
let containerHeight = this._tooltip.panel.getBoundingClientRect().height;
|
||||
if (top < 0) {
|
||||
// Element is above container.
|
||||
element.scrollIntoView(true);
|
||||
} else if ((top + height) > containerHeight) {
|
||||
// Element is beloew container.
|
||||
element.scrollIntoView(false);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -320,22 +289,10 @@ AutocompletePopup.prototype = {
|
|||
clearItems: function () {
|
||||
// Reset the selectedIndex to -1 before clearing the list
|
||||
this.selectedIndex = -1;
|
||||
|
||||
while (this._list.hasChildNodes()) {
|
||||
this._list.removeChild(this._list.firstChild);
|
||||
}
|
||||
|
||||
this._list.innerHTML = "";
|
||||
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 = "";
|
||||
this.items = [];
|
||||
this.elements = new WeakMap();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -344,7 +301,7 @@ AutocompletePopup.prototype = {
|
|||
* @type {Number}
|
||||
*/
|
||||
get selectedIndex() {
|
||||
return this._list.selectedIndex;
|
||||
return this._selectedIndex;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -354,11 +311,24 @@ AutocompletePopup.prototype = {
|
|||
* The number (index) of the item you want to select in the list.
|
||||
*/
|
||||
set selectedIndex(index) {
|
||||
this._list.selectedIndex = index;
|
||||
if (this.isOpen && this._list.ensureIndexIsVisible) {
|
||||
this._list.ensureIndexIsVisible(this._list.selectedIndex);
|
||||
let previousSelected = this._list.querySelector(".autocomplete-selected");
|
||||
if (previousSelected) {
|
||||
previousSelected.classList.remove("autocomplete-selected");
|
||||
}
|
||||
|
||||
let item = this.items[index];
|
||||
if (this.isOpen && item) {
|
||||
let element = this.elements.get(item);
|
||||
|
||||
element.classList.add("autocomplete-selected");
|
||||
this._scrollElementIntoViewIfNeeded(element);
|
||||
}
|
||||
this._selectedIndex = index;
|
||||
|
||||
if (this.isOpen && item && this.onSelectCallback) {
|
||||
// Call the user-defined select callback if defined.
|
||||
this.onSelectCallback();
|
||||
}
|
||||
this._updateAriaActiveDescendant();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -366,8 +336,7 @@ AutocompletePopup.prototype = {
|
|||
* @type Object
|
||||
*/
|
||||
get selectedItem() {
|
||||
return this._list.selectedItem ?
|
||||
this._list.selectedItem._autocompleteItem : null;
|
||||
return this.items[this._selectedIndex];
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -377,11 +346,10 @@ AutocompletePopup.prototype = {
|
|||
* The object you want selected in the list.
|
||||
*/
|
||||
set selectedItem(item) {
|
||||
this._list.selectedItem = this._findListItem(item);
|
||||
if (this.isOpen) {
|
||||
this._list.ensureIndexIsVisible(this._list.selectedIndex);
|
||||
let index = this.items.indexOf(item);
|
||||
if (index !== -1 && this.isOpen) {
|
||||
this.selectedIndex = index;
|
||||
}
|
||||
this._updateAriaActiveDescendant();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -401,54 +369,36 @@ AutocompletePopup.prototype = {
|
|||
* autocompleted label.
|
||||
*/
|
||||
appendItem: function (item) {
|
||||
let listItem = this._document.createElementNS(XUL_NS, "richlistitem");
|
||||
let listItem = this._document.createElementNS(HTML_NS, "li");
|
||||
// Items must have an id for accessibility.
|
||||
listItem.id = this._panel.id + "_item_" + this._itemIdCounter++;
|
||||
listItem.setAttribute("id", "autocomplete-item-" + itemIdCounter++);
|
||||
listItem.className = "autocomplete-item";
|
||||
listItem.setAttribute("data-index", this.items.length);
|
||||
if (this.direction) {
|
||||
listItem.setAttribute("dir", this.direction);
|
||||
}
|
||||
let label = this._document.createElementNS(XUL_NS, "label");
|
||||
label.setAttribute("value", item.label);
|
||||
label.setAttribute("class", "autocomplete-value");
|
||||
let label = this._document.createElementNS(HTML_NS, "span");
|
||||
label.textContent = item.label;
|
||||
label.className = "autocomplete-value";
|
||||
if (item.preLabel) {
|
||||
let preDesc = this._document.createElementNS(XUL_NS, "label");
|
||||
preDesc.setAttribute("value", item.preLabel);
|
||||
preDesc.setAttribute("class", "initial-value");
|
||||
let preDesc = this._document.createElementNS(HTML_NS, "span");
|
||||
preDesc.textContent = item.preLabel;
|
||||
preDesc.className = "initial-value";
|
||||
listItem.appendChild(preDesc);
|
||||
label.setAttribute("value", item.label.slice(item.preLabel.length));
|
||||
label.textContent = item.label.slice(item.preLabel.length);
|
||||
}
|
||||
listItem.appendChild(label);
|
||||
if (item.count && item.count > 1) {
|
||||
let countDesc = this._document.createElementNS(XUL_NS, "label");
|
||||
countDesc.setAttribute("value", item.count);
|
||||
let countDesc = this._document.createElementNS(HTML_NS, "span");
|
||||
countDesc.textContent = item.count;
|
||||
countDesc.setAttribute("flex", "1");
|
||||
countDesc.setAttribute("class", "autocomplete-count");
|
||||
countDesc.className = "autocomplete-count";
|
||||
listItem.appendChild(countDesc);
|
||||
}
|
||||
listItem._autocompleteItem = item;
|
||||
|
||||
this._list.appendChild(listItem);
|
||||
},
|
||||
|
||||
/**
|
||||
* Find the richlistitem element that belongs to an item.
|
||||
*
|
||||
* @private
|
||||
*
|
||||
* @param {Object} item
|
||||
* The object you want found in the list.
|
||||
*
|
||||
* @return {nsIDOMNode} The nsIDOMNode that belongs to the given item object.
|
||||
* This node is the richlistitem element. Can be null.
|
||||
*/
|
||||
_findListItem: function (item) {
|
||||
for (let i = 0; i < this._list.childNodes.length; i++) {
|
||||
let child = this._list.childNodes[i];
|
||||
if (child._autocompleteItem == item) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
this.items.push(item);
|
||||
this.elements.set(item, listItem);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -458,11 +408,26 @@ AutocompletePopup.prototype = {
|
|||
* The item you want removed.
|
||||
*/
|
||||
removeItem: function (item) {
|
||||
let listItem = this._findListItem(item);
|
||||
if (!listItem) {
|
||||
throw new Error("Item not found!");
|
||||
if (!this.items.includes(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let itemIndex = this.items.indexOf(item);
|
||||
let selectedIndex = this.selectedIndex;
|
||||
|
||||
// Remove autocomplete item.
|
||||
this.items.splice(itemIndex, 1);
|
||||
|
||||
// Remove corresponding DOM element from the elements WeakMap and from the DOM.
|
||||
let elementToRemove = this.elements.get(item);
|
||||
this.elements.delete(elementToRemove);
|
||||
elementToRemove.remove();
|
||||
|
||||
if (itemIndex <= selectedIndex) {
|
||||
// If the removed item index was before or equal to the selected index, shift the
|
||||
// selected index by 1.
|
||||
this.selectedIndex = Math.max(0, selectedIndex - 1);
|
||||
}
|
||||
this._list.removeChild(listItem);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -470,7 +435,7 @@ AutocompletePopup.prototype = {
|
|||
* @type {Number}
|
||||
*/
|
||||
get itemCount() {
|
||||
return this._list.childNodes.length;
|
||||
return this.items.length;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -478,8 +443,14 @@ AutocompletePopup.prototype = {
|
|||
*
|
||||
* @type {Number}
|
||||
*/
|
||||
get _itemHeight() {
|
||||
return this._list.selectedItem.clientHeight;
|
||||
get _itemsPerPane() {
|
||||
if (this.items.length) {
|
||||
let listHeight = this._tooltip.panel.clientHeight;
|
||||
let element = this.elements.get(this.items[0]);
|
||||
let elementHeight = element.getBoundingClientRect().height;
|
||||
return Math.floor(listHeight / elementHeight);
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -489,12 +460,11 @@ AutocompletePopup.prototype = {
|
|||
* The newly selected item object.
|
||||
*/
|
||||
selectNextItem: function () {
|
||||
if (this.selectedIndex < (this.itemCount - 1)) {
|
||||
if (this.selectedIndex < (this.items.length - 1)) {
|
||||
this.selectedIndex++;
|
||||
} else {
|
||||
this.selectedIndex = 0;
|
||||
}
|
||||
|
||||
return this.selectedItem;
|
||||
},
|
||||
|
||||
|
@ -508,7 +478,7 @@ AutocompletePopup.prototype = {
|
|||
if (this.selectedIndex > 0) {
|
||||
this.selectedIndex--;
|
||||
} else {
|
||||
this.selectedIndex = this.itemCount - 1;
|
||||
this.selectedIndex = this.items.length - 1;
|
||||
}
|
||||
|
||||
return this.selectedItem;
|
||||
|
@ -522,11 +492,8 @@ AutocompletePopup.prototype = {
|
|||
* The newly-selected item object.
|
||||
*/
|
||||
selectNextPageItem: function () {
|
||||
let itemsPerPane = Math.floor(this._list.scrollHeight / this._itemHeight);
|
||||
let nextPageIndex = this.selectedIndex + itemsPerPane + 1;
|
||||
this.selectedIndex = nextPageIndex > this.itemCount - 1 ?
|
||||
this.itemCount - 1 : nextPageIndex;
|
||||
|
||||
let nextPageIndex = this.selectedIndex + this._itemsPerPane + 1;
|
||||
this.selectedIndex = Math.min(nextPageIndex, this.itemCount - 1);
|
||||
return this.selectedItem;
|
||||
},
|
||||
|
||||
|
@ -538,20 +505,11 @@ AutocompletePopup.prototype = {
|
|||
* The newly-selected item object.
|
||||
*/
|
||||
selectPreviousPageItem: function () {
|
||||
let itemsPerPane = Math.floor(this._list.scrollHeight / this._itemHeight);
|
||||
let prevPageIndex = this.selectedIndex - itemsPerPane - 1;
|
||||
this.selectedIndex = prevPageIndex < 0 ? 0 : prevPageIndex;
|
||||
|
||||
let prevPageIndex = this.selectedIndex - this._itemsPerPane - 1;
|
||||
this.selectedIndex = Math.max(prevPageIndex, 0);
|
||||
return this.selectedItem;
|
||||
},
|
||||
|
||||
/**
|
||||
* Focuses the richlistbox.
|
||||
*/
|
||||
focus: function () {
|
||||
this._list.focus();
|
||||
},
|
||||
|
||||
/**
|
||||
* Manages theme switching for the popup based on the devtools.theme pref.
|
||||
*
|
||||
|
@ -567,11 +525,25 @@ AutocompletePopup.prototype = {
|
|||
* - oldValue {Object} The old value of the preference.
|
||||
*/
|
||||
_handleThemeChange: function (event, data) {
|
||||
if (data.pref == "devtools.theme") {
|
||||
this._panel.classList.toggle(data.oldValue + "-theme", false);
|
||||
this._panel.classList.toggle(data.newValue + "-theme", true);
|
||||
if (data.pref === "devtools.theme") {
|
||||
this._tooltip.panel.classList.toggle(data.oldValue + "-theme", false);
|
||||
this._tooltip.panel.classList.toggle(data.newValue + "-theme", true);
|
||||
this._list.classList.toggle(data.oldValue + "-theme", false);
|
||||
this._list.classList.toggle(data.newValue + "-theme", true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Used by tests.
|
||||
*/
|
||||
get _panel() {
|
||||
return this._tooltip.panel;
|
||||
},
|
||||
|
||||
/**
|
||||
* Used by tests.
|
||||
*/
|
||||
get _window() {
|
||||
return this._document.defaultView;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -93,18 +93,6 @@ define(function (require, exports, module) {
|
|||
return items;
|
||||
},
|
||||
|
||||
hasSpecialProperties: function (array) {
|
||||
return false;
|
||||
},
|
||||
|
||||
// Event Handlers
|
||||
|
||||
onToggleProperties: function (event) {
|
||||
},
|
||||
|
||||
onClickBracket: function (event) {
|
||||
},
|
||||
|
||||
render: function () {
|
||||
let mode = this.props.mode || "short";
|
||||
let object = this.props.object;
|
||||
|
@ -119,12 +107,8 @@ define(function (require, exports, module) {
|
|||
}
|
||||
|
||||
return (
|
||||
ObjectBox({
|
||||
className: "array",
|
||||
onClick: this.onToggleProperties},
|
||||
a({
|
||||
className: "objectLink",
|
||||
onclick: this.onClickBracket},
|
||||
ObjectBox({className: "array"},
|
||||
a({className: "objectLink"},
|
||||
span({
|
||||
className: "arrayLeftBracket",
|
||||
role: "presentation"},
|
||||
|
@ -132,9 +116,7 @@ define(function (require, exports, module) {
|
|||
)
|
||||
),
|
||||
items,
|
||||
a({
|
||||
className: "objectLink",
|
||||
onclick: this.onClickBracket},
|
||||
a({className: "objectLink"},
|
||||
span({
|
||||
className: "arrayRightBracket",
|
||||
role: "presentation"},
|
||||
|
|
|
@ -11,6 +11,7 @@ support-files =
|
|||
[test_reps_date-time.html]
|
||||
[test_reps_function.html]
|
||||
[test_reps_grip.html]
|
||||
[test_reps_grip-array.html]
|
||||
[test_reps_null.html]
|
||||
[test_reps_number.html]
|
||||
[test_reps_object-with-text.html]
|
||||
|
|
|
@ -0,0 +1,262 @@
|
|||
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test GripArray rep
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Rep test - GripArray</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script src="head.js" type="application/javascript;version=1.8"></script>
|
||||
<script type="application/javascript;version=1.8">
|
||||
window.onload = Task.async(function* () {
|
||||
let { Rep } = browserRequire("devtools/client/shared/components/reps/rep");
|
||||
let { GripArray } = browserRequire("devtools/client/shared/components/reps/grip-array");
|
||||
|
||||
let componentUnderTest = GripArray;
|
||||
|
||||
try {
|
||||
yield testBasic();
|
||||
|
||||
// Test property iterator
|
||||
yield testMaxProps();
|
||||
yield testMoreThanMaxProps();
|
||||
yield testRecursiveArray();
|
||||
} catch(e) {
|
||||
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
|
||||
} finally {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function testBasic() {
|
||||
// Test array: `[]`
|
||||
const testName = "testBasic";
|
||||
|
||||
// Test that correct rep is chosen
|
||||
const gripStub = getGripStub("testBasic");
|
||||
const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
|
||||
is(renderedRep.type, GripArray.rep, `Rep correctly selects ${GripArray.rep.displayName}`);
|
||||
|
||||
// Test rendering
|
||||
const defaultOutput = `[]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
mode: undefined,
|
||||
expectedOutput: defaultOutput,
|
||||
},
|
||||
{
|
||||
mode: "tiny",
|
||||
expectedOutput: `[0]`,
|
||||
},
|
||||
{
|
||||
mode: "short",
|
||||
expectedOutput: defaultOutput,
|
||||
},
|
||||
{
|
||||
mode: "long",
|
||||
expectedOutput: defaultOutput,
|
||||
}
|
||||
];
|
||||
|
||||
testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
|
||||
}
|
||||
|
||||
function testMaxProps() {
|
||||
// Test array: `[1, "foo", {}]`;
|
||||
const testName = "testMaxProps";
|
||||
|
||||
const defaultOutput = `[1, "foo", Object]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
mode: undefined,
|
||||
expectedOutput: defaultOutput,
|
||||
},
|
||||
{
|
||||
mode: "tiny",
|
||||
expectedOutput: `[3]`,
|
||||
},
|
||||
{
|
||||
mode: "short",
|
||||
expectedOutput: defaultOutput,
|
||||
},
|
||||
{
|
||||
mode: "long",
|
||||
expectedOutput: defaultOutput,
|
||||
}
|
||||
];
|
||||
|
||||
testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
|
||||
}
|
||||
|
||||
function testMoreThanMaxProps() {
|
||||
// Test array = `["test string"...] //301 items`
|
||||
const testName = "testMoreThanMaxProps";
|
||||
|
||||
const defaultOutput = `[${Array(3).fill("\"test string\"").join(", ")}, more...]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
mode: undefined,
|
||||
expectedOutput: defaultOutput,
|
||||
},
|
||||
{
|
||||
mode: "tiny",
|
||||
expectedOutput: `[302]`,
|
||||
},
|
||||
{
|
||||
mode: "short",
|
||||
expectedOutput: defaultOutput,
|
||||
},
|
||||
{
|
||||
mode: "long",
|
||||
expectedOutput: `[${Array(300).fill("\"test string\"").join(", ")}, more...]`,
|
||||
}
|
||||
];
|
||||
|
||||
testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
|
||||
}
|
||||
|
||||
function testRecursiveArray() {
|
||||
// @TODO This is not how this feature should actually work
|
||||
// See Bug 1282465 - Reps: fix or remove recursive handling in grip-array
|
||||
|
||||
// Test array = `let a = []; a = [a]`
|
||||
const testName = "testRecursiveArray";
|
||||
|
||||
const defaultOutput = `[[1]]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
mode: undefined,
|
||||
expectedOutput: defaultOutput,
|
||||
},
|
||||
{
|
||||
mode: "tiny",
|
||||
expectedOutput: `[1]`,
|
||||
},
|
||||
{
|
||||
mode: "short",
|
||||
expectedOutput: defaultOutput,
|
||||
},
|
||||
{
|
||||
mode: "long",
|
||||
expectedOutput: defaultOutput,
|
||||
}
|
||||
];
|
||||
|
||||
testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
|
||||
}
|
||||
|
||||
function getGripStub(functionName) {
|
||||
switch (functionName) {
|
||||
case "testBasic":
|
||||
return {
|
||||
"type": "object",
|
||||
"class": "Array",
|
||||
"actor": "server1.conn0.obj35",
|
||||
"extensible": true,
|
||||
"frozen": false,
|
||||
"sealed": false,
|
||||
"ownPropertyLength": 1,
|
||||
"preview": {
|
||||
"kind": "ArrayLike",
|
||||
"length": 0,
|
||||
"items": []
|
||||
}
|
||||
};
|
||||
|
||||
case "testMaxProps":
|
||||
return {
|
||||
"type": "object",
|
||||
"class": "Array",
|
||||
"actor": "server1.conn1.obj35",
|
||||
"extensible": true,
|
||||
"frozen": false,
|
||||
"sealed": false,
|
||||
"ownPropertyLength": 4,
|
||||
"preview": {
|
||||
"kind": "ArrayLike",
|
||||
"length": 3,
|
||||
"items": [
|
||||
1,
|
||||
"foo",
|
||||
{
|
||||
"type": "object",
|
||||
"class": "Object",
|
||||
"actor": "server1.conn1.obj36",
|
||||
"extensible": true,
|
||||
"frozen": false,
|
||||
"sealed": false,
|
||||
"ownPropertyLength": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
case "testMoreThanMaxProps":
|
||||
let grip = {
|
||||
"type": "object",
|
||||
"class": "Array",
|
||||
"actor": "server1.conn1.obj35",
|
||||
"extensible": true,
|
||||
"frozen": false,
|
||||
"sealed": false,
|
||||
"ownPropertyLength": 4,
|
||||
"preview": {
|
||||
"kind": "ArrayLike",
|
||||
"length": 302,
|
||||
"items": []
|
||||
}
|
||||
};
|
||||
|
||||
// Generate 101 properties, which is more that the maximum
|
||||
// limit in case of the 'long' mode.
|
||||
for (let i = 0; i < 302; i++) {
|
||||
grip.preview.items.push("test string");
|
||||
}
|
||||
|
||||
return grip;
|
||||
|
||||
case "testRecursiveArray":
|
||||
return {
|
||||
"type": "object",
|
||||
"class": "Array",
|
||||
"actor": "server1.conn3.obj42",
|
||||
"extensible": true,
|
||||
"frozen": false,
|
||||
"sealed": false,
|
||||
"ownPropertyLength": 2,
|
||||
"preview": {
|
||||
"kind": "ArrayLike",
|
||||
"length": 1,
|
||||
"items": [
|
||||
{
|
||||
"type": "object",
|
||||
"class": "Array",
|
||||
"actor": "server1.conn3.obj43",
|
||||
"extensible": true,
|
||||
"frozen": false,
|
||||
"sealed": false,
|
||||
"ownPropertyLength": 2,
|
||||
"preview": {
|
||||
"kind": "ArrayLike",
|
||||
"length": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -33,7 +33,6 @@ const CONTENT_TYPES = {
|
|||
CSS_MIXED: 2,
|
||||
CSS_PROPERTY: 3,
|
||||
};
|
||||
const AUTOCOMPLETE_POPUP_CLASSNAME = "inplace-editor-autocomplete-popup";
|
||||
|
||||
// The limit of 500 autocomplete suggestions should not be reached but is kept
|
||||
// for safety.
|
||||
|
@ -989,13 +988,13 @@ InplaceEditor.prototype = {
|
|||
let label, preLabel;
|
||||
|
||||
if (this._selectedIndex === undefined) {
|
||||
({label, preLabel} =
|
||||
this.popup.getItemAtIndex(this.popup.selectedIndex));
|
||||
({label, preLabel} = this.popup.getItemAtIndex(this.popup.selectedIndex));
|
||||
} else {
|
||||
({label, preLabel} = this.popup.getItemAtIndex(this._selectedIndex));
|
||||
}
|
||||
|
||||
let input = this.input;
|
||||
|
||||
let pre = "";
|
||||
|
||||
// CSS_MIXED needs special treatment here to make it so that
|
||||
|
@ -1021,13 +1020,13 @@ InplaceEditor.prototype = {
|
|||
// Wait for the popup to hide and then focus input async otherwise it does
|
||||
// not work.
|
||||
let onPopupHidden = () => {
|
||||
this.popup._panel.removeEventListener("popuphidden", onPopupHidden);
|
||||
this.popup.off("popup-closed", onPopupHidden);
|
||||
this.doc.defaultView.setTimeout(()=> {
|
||||
input.focus();
|
||||
this.emit("after-suggest");
|
||||
}, 0);
|
||||
};
|
||||
this.popup._panel.addEventListener("popuphidden", onPopupHidden);
|
||||
this.popup.on("popup-closed", onPopupHidden);
|
||||
this._hideAutocompletePopup();
|
||||
},
|
||||
|
||||
|
@ -1174,7 +1173,6 @@ InplaceEditor.prototype = {
|
|||
* item selected.
|
||||
*/
|
||||
_openAutocompletePopup: function (offset, selectedIndex) {
|
||||
this.popup._panel.classList.add(AUTOCOMPLETE_POPUP_CLASSNAME);
|
||||
this.popup.on("popup-click", this._onAutocompletePopupClick);
|
||||
this.popup.openPopup(this.input, offset, 0, selectedIndex);
|
||||
},
|
||||
|
@ -1184,7 +1182,6 @@ InplaceEditor.prototype = {
|
|||
* popup.
|
||||
*/
|
||||
_hideAutocompletePopup: function () {
|
||||
this.popup._panel.classList.remove(AUTOCOMPLETE_POPUP_CLASSNAME);
|
||||
this.popup.off("popup-click", this._onAutocompletePopupClick);
|
||||
this.popup.hidePopup();
|
||||
},
|
||||
|
|
|
@ -6,16 +6,16 @@
|
|||
|
||||
// Tests that the CubicBezierWidget generates content in a given parent node
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/cubic-bezier-frame.xhtml";
|
||||
const {CubicBezierWidget} =
|
||||
require("devtools/client/shared/widgets/CubicBezierWidget");
|
||||
|
||||
const TEST_URI = `data:text/html,<div id="cubic-bezier-container" />`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
info("Checking that the graph markup is created in the parent");
|
||||
let container = doc.querySelector("#container");
|
||||
let container = doc.querySelector("#cubic-bezier-container");
|
||||
let w = new CubicBezierWidget(container);
|
||||
|
||||
ok(container.querySelector(".display-wrap"),
|
||||
|
@ -27,9 +27,7 @@ add_task(function* () {
|
|||
is(buttons.length, 2,
|
||||
"The 2 control points have been added");
|
||||
is(buttons[0].className, "control-point");
|
||||
is(buttons[0].id, "P1");
|
||||
is(buttons[1].className, "control-point");
|
||||
is(buttons[1].id, "P2");
|
||||
ok(container.querySelector("canvas"), "The curve canvas has been added");
|
||||
|
||||
info("Destroying the widget");
|
||||
|
@ -37,5 +35,4 @@ add_task(function* () {
|
|||
is(container.children.length, 0, "All nodes have been removed");
|
||||
|
||||
host.destroy();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
|
|
@ -6,21 +6,26 @@
|
|||
|
||||
// Tests the CubicBezierWidget events
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/cubic-bezier-frame.xhtml";
|
||||
const {CubicBezierWidget} =
|
||||
require("devtools/client/shared/widgets/CubicBezierWidget");
|
||||
const {PREDEFINED} = require("devtools/client/shared/widgets/CubicBezierPresets");
|
||||
|
||||
// In this test we have to use a slightly more complete HTML tree, with <body>
|
||||
// in order to remove its margin and prevent shifted positions
|
||||
const TEST_URI = `data:text/html,
|
||||
<html><body>
|
||||
<div id="cubic-bezier-container"/>
|
||||
</body></html>`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
// Required or widget will be clipped inside of 'bottom'
|
||||
// host by -14. Setting `fixed` zeroes this which is needed for
|
||||
// calculating offsets. Occurs in test env only.
|
||||
doc.body.setAttribute("style", "position: fixed");
|
||||
doc.body.setAttribute("style", "position: fixed; margin: 0;");
|
||||
|
||||
let container = doc.querySelector("#container");
|
||||
let container = doc.querySelector("#cubic-bezier-container");
|
||||
let w = new CubicBezierWidget(container, PREDEFINED.linear);
|
||||
|
||||
let rect = w.curve.getBoundingClientRect();
|
||||
|
@ -34,7 +39,6 @@ add_task(function* () {
|
|||
|
||||
w.destroy();
|
||||
host.destroy();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
function* pointsCanBeDragged(widget, win, doc, offsets) {
|
||||
|
|
|
@ -6,16 +6,16 @@
|
|||
|
||||
// Tests that coordinates can be changed programatically in the CubicBezierWidget
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/cubic-bezier-frame.xhtml";
|
||||
const {CubicBezierWidget} =
|
||||
require("devtools/client/shared/widgets/CubicBezierWidget");
|
||||
const {PREDEFINED} = require("devtools/client/shared/widgets/CubicBezierPresets");
|
||||
|
||||
const TEST_URI = `data:text/html,<div id="cubic-bezier-container" />`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
let container = doc.querySelector("#container");
|
||||
let container = doc.querySelector("#cubic-bezier-container");
|
||||
let w = new CubicBezierWidget(container, PREDEFINED.linear);
|
||||
|
||||
yield coordinatesCanBeChangedByProvidingAnArray(w);
|
||||
|
@ -23,7 +23,6 @@ add_task(function* () {
|
|||
|
||||
w.destroy();
|
||||
host.destroy();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
function* coordinatesCanBeChangedByProvidingAnArray(widget) {
|
||||
|
|
|
@ -6,16 +6,16 @@
|
|||
|
||||
// Tests that the CubicBezierPresetWidget generates markup.
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/cubic-bezier-frame.xhtml";
|
||||
const {CubicBezierPresetWidget} =
|
||||
require("devtools/client/shared/widgets/CubicBezierWidget");
|
||||
const {PRESETS} = require("devtools/client/shared/widgets/CubicBezierPresets");
|
||||
|
||||
const TEST_URI = `data:text/html,<div id="cubic-bezier-container" />`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
let container = doc.querySelector("#container");
|
||||
let container = doc.querySelector("#cubic-bezier-container");
|
||||
let w = new CubicBezierPresetWidget(container);
|
||||
|
||||
info("Checking that the presets are created in the parent");
|
||||
|
@ -47,5 +47,4 @@ add_task(function* () {
|
|||
|
||||
w.destroy();
|
||||
host.destroy();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
|
|
@ -6,17 +6,17 @@
|
|||
|
||||
// Tests that the CubicBezierPresetWidget cycles menus
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/cubic-bezier-frame.xhtml";
|
||||
const {CubicBezierPresetWidget} =
|
||||
require("devtools/client/shared/widgets/CubicBezierWidget");
|
||||
const {PREDEFINED, PRESETS, DEFAULT_PRESET_CATEGORY} =
|
||||
require("devtools/client/shared/widgets/CubicBezierPresets");
|
||||
|
||||
const TEST_URI = `data:text/html,<div id="cubic-bezier-container" />`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
let container = doc.querySelector("#container");
|
||||
let container = doc.querySelector("#cubic-bezier-container");
|
||||
let w = new CubicBezierPresetWidget(container);
|
||||
|
||||
info("Checking that preset is selected if coordinates are known");
|
||||
|
@ -45,5 +45,4 @@ add_task(function* () {
|
|||
|
||||
w.destroy();
|
||||
host.destroy();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
|
|
@ -7,16 +7,16 @@
|
|||
|
||||
// Tests the integration between CubicBezierWidget and CubicBezierPresets
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/cubic-bezier-frame.xhtml";
|
||||
const {CubicBezierWidget} =
|
||||
require("devtools/client/shared/widgets/CubicBezierWidget");
|
||||
const {PRESETS} = require("devtools/client/shared/widgets/CubicBezierPresets");
|
||||
|
||||
const TEST_URI = `data:text/html,<div id="cubic-bezier-container" />`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
let container = doc.querySelector("#container");
|
||||
let container = doc.querySelector("#cubic-bezier-container");
|
||||
let w = new CubicBezierWidget(container,
|
||||
PRESETS["ease-in"]["ease-in-sine"]);
|
||||
w.presets.refreshMenu(PRESETS["ease-in"]["ease-in-sine"]);
|
||||
|
@ -29,7 +29,6 @@ add_task(function* () {
|
|||
|
||||
w.destroy();
|
||||
host.destroy();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
function* adjustingBezierUpdatesPreset(widget, win, doc, rect) {
|
||||
|
|
|
@ -5,11 +5,12 @@
|
|||
|
||||
// Tests that the Filter Editor Widget parses filter values correctly (setCssValue)
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/filter-frame.xhtml";
|
||||
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
|
||||
const DOMUtils =
|
||||
Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
||||
|
||||
const TEST_URI = `data:text/html,<div id="filter-container" />`;
|
||||
|
||||
// Verify that the given string consists of a valid CSS URL token.
|
||||
// Return true on success, false on error.
|
||||
function verifyURL(string) {
|
||||
|
@ -24,10 +25,9 @@ function verifyURL(string) {
|
|||
}
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
const container = doc.querySelector("#container");
|
||||
const container = doc.querySelector("#filter-container");
|
||||
let widget = new CSSFilterEditorWidget(container, "none");
|
||||
|
||||
info("Test parsing of a valid CSS Filter value");
|
||||
|
|
|
@ -5,15 +5,15 @@
|
|||
|
||||
// Tests that the Filter Editor Widget renders filters correctly
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/filter-frame.xhtml";
|
||||
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
|
||||
|
||||
const { LocalizationHelper } = require("devtools/client/shared/l10n");
|
||||
const STRINGS_URI = "chrome://devtools/locale/filterwidget.properties";
|
||||
const L10N = new LocalizationHelper(STRINGS_URI);
|
||||
|
||||
const TEST_URI = `data:text/html,<div id="filter-container" />`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
const TEST_DATA = [
|
||||
|
@ -68,7 +68,7 @@ add_task(function* () {
|
|||
}
|
||||
];
|
||||
|
||||
const container = doc.querySelector("#container");
|
||||
const container = doc.querySelector("#filter-container");
|
||||
let widget = new CSSFilterEditorWidget(container, "none");
|
||||
|
||||
info("Test rendering of different types");
|
||||
|
|
|
@ -5,17 +5,16 @@
|
|||
|
||||
// Tests the Filter Editor Widget add, removeAt, updateAt, getValueAt methods
|
||||
|
||||
const BASE_URI = "chrome://devtools/content/shared/widgets/";
|
||||
const TEST_URI = BASE_URI + "filter-frame.xhtml";
|
||||
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
|
||||
const GRAYSCALE_MAX = 100;
|
||||
const INVERT_MIN = 0;
|
||||
|
||||
const TEST_URI = `data:text/html,<div id="filter-container" />`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
const container = doc.querySelector("#container");
|
||||
const container = doc.querySelector("#filter-container");
|
||||
let widget = new CSSFilterEditorWidget(container, "none");
|
||||
|
||||
info("Test add method");
|
||||
|
|
|
@ -5,15 +5,15 @@
|
|||
|
||||
// Tests the Filter Editor Widget's drag-drop re-ordering
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/filter-frame.xhtml";
|
||||
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
|
||||
const LIST_ITEM_HEIGHT = 32;
|
||||
|
||||
const TEST_URI = `data:text/html,<div id="filter-container" />`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
const container = doc.querySelector("#container");
|
||||
const container = doc.querySelector("#filter-container");
|
||||
const initialValue = "blur(2px) contrast(200%) brightness(200%)";
|
||||
let widget = new CSSFilterEditorWidget(container, initialValue);
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ requestLongerTimeout(2);
|
|||
|
||||
// Tests the Filter Editor Widget's label-dragging
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/filter-frame.xhtml";
|
||||
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
|
||||
|
||||
const FAST_VALUE_MULTIPLIER = 10;
|
||||
|
@ -17,11 +16,12 @@ const DEFAULT_VALUE_MULTIPLIER = 1;
|
|||
const GRAYSCALE_MAX = 100,
|
||||
GRAYSCALE_MIN = 0;
|
||||
|
||||
const TEST_URI = `data:text/html,<div id="filter-container" />`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
const container = doc.querySelector("#container");
|
||||
const container = doc.querySelector("#filter-container");
|
||||
let widget = new CSSFilterEditorWidget(container, "grayscale(0%) url(test.svg)");
|
||||
|
||||
const filters = widget.el.querySelector("#filters");
|
||||
|
|
|
@ -5,19 +5,18 @@
|
|||
|
||||
// Tests the Filter Editor Widget's add button
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/filter-frame.xhtml";
|
||||
|
||||
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
|
||||
|
||||
const { LocalizationHelper } = require("devtools/client/shared/l10n");
|
||||
const STRINGS_URI = "chrome://devtools/locale/filterwidget.properties";
|
||||
const L10N = new LocalizationHelper(STRINGS_URI);
|
||||
|
||||
const TEST_URI = `data:text/html,<div id="filter-container" />`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
const container = doc.querySelector("#container");
|
||||
const container = doc.querySelector("#filter-container");
|
||||
let widget = new CSSFilterEditorWidget(container, "none");
|
||||
|
||||
const select = widget.el.querySelector("select"),
|
||||
|
|
|
@ -5,19 +5,18 @@
|
|||
|
||||
// Tests the Filter Editor Widget's remove button
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/filter-frame.xhtml";
|
||||
|
||||
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
|
||||
|
||||
const { LocalizationHelper } = require("devtools/client/shared/l10n");
|
||||
const STRINGS_URI = "chrome://devtools/locale/filterwidget.properties";
|
||||
const L10N = new LocalizationHelper(STRINGS_URI);
|
||||
|
||||
const TEST_URI = `data:text/html,<div id="filter-container" />`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
const container = doc.querySelector("#container");
|
||||
const container = doc.querySelector("#filter-container");
|
||||
let widget = new CSSFilterEditorWidget(container, "blur(2px) contrast(200%)");
|
||||
|
||||
info("Test removing filters with remove button");
|
||||
|
|
|
@ -6,18 +6,18 @@
|
|||
// Tests the Filter Editor Widget inputs increase/decrease value using
|
||||
// arrow keys, applying multiplier using alt/shift on number-type filters
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/filter-frame.xhtml";
|
||||
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
|
||||
|
||||
const FAST_VALUE_MULTIPLIER = 10;
|
||||
const SLOW_VALUE_MULTIPLIER = 0.1;
|
||||
const DEFAULT_VALUE_MULTIPLIER = 1;
|
||||
|
||||
const TEST_URI = `data:text/html,<div id="filter-container" />`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
const container = doc.querySelector("#container");
|
||||
const container = doc.querySelector("#filter-container");
|
||||
const initialValue = "blur(2px)";
|
||||
let widget = new CSSFilterEditorWidget(container, initialValue);
|
||||
|
||||
|
|
|
@ -6,18 +6,18 @@
|
|||
// Tests the Filter Editor Widget inputs increase/decrease value when cursor is
|
||||
// on a number using arrow keys, applying multiplier using alt/shift on strings
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/filter-frame.xhtml";
|
||||
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
|
||||
|
||||
const FAST_VALUE_MULTIPLIER = 10;
|
||||
const SLOW_VALUE_MULTIPLIER = 0.1;
|
||||
const DEFAULT_VALUE_MULTIPLIER = 1;
|
||||
|
||||
const TEST_URI = `data:text/html,<div id="filter-container" />`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
const container = doc.querySelector("#container");
|
||||
const container = doc.querySelector("#filter-container");
|
||||
const initialValue = "drop-shadow(rgb(0, 0, 0) 1px 1px 0px)";
|
||||
let widget = new CSSFilterEditorWidget(container, initialValue);
|
||||
widget.el.querySelector("#filters input").setSelectionRange(13, 13);
|
||||
|
|
|
@ -6,18 +6,18 @@
|
|||
// Tests the Filter Editor Widget inputs increase/decrease value when cursor is
|
||||
// on a number using arrow keys if cursor is behind/mid/after the number strings
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/filter-frame.xhtml";
|
||||
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
|
||||
|
||||
const FAST_VALUE_MULTIPLIER = 10;
|
||||
const SLOW_VALUE_MULTIPLIER = 0.1;
|
||||
const DEFAULT_VALUE_MULTIPLIER = 1;
|
||||
|
||||
const TEST_URI = `data:text/html,<div id="filter-container" />`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
const container = doc.querySelector("#container");
|
||||
const container = doc.querySelector("#filter-container");
|
||||
const initialValue = "drop-shadow(rgb(0, 0, 0) 10px 1px 0px)";
|
||||
let widget = new CSSFilterEditorWidget(container, initialValue);
|
||||
const input = widget.el.querySelector("#filters input");
|
||||
|
|
|
@ -5,15 +5,14 @@
|
|||
|
||||
// Tests saving presets
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/filter-frame.xhtml";
|
||||
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
const TEST_URI = `data:text/html,<div id="filter-container" />`;
|
||||
|
||||
add_task(function* () {
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
const container = doc.querySelector("#container");
|
||||
const container = doc.querySelector("#filter-container");
|
||||
let widget = new CSSFilterEditorWidget(container, "none");
|
||||
// First render
|
||||
yield widget.once("render");
|
||||
|
|
|
@ -5,15 +5,14 @@
|
|||
|
||||
// Tests loading presets
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/filter-frame.xhtml";
|
||||
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
const TEST_URI = `data:text/html,<div id="filter-container" />`;
|
||||
|
||||
add_task(function* () {
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
const container = doc.querySelector("#container");
|
||||
const container = doc.querySelector("#filter-container");
|
||||
let widget = new CSSFilterEditorWidget(container, "none");
|
||||
// First render
|
||||
yield widget.once("render");
|
||||
|
|
|
@ -5,15 +5,14 @@
|
|||
|
||||
// Tests deleting presets
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/filter-frame.xhtml";
|
||||
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
const TEST_URI = `data:text/html,<div id="filter-container" />`;
|
||||
|
||||
add_task(function* () {
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
const container = doc.querySelector("#container");
|
||||
const container = doc.querySelector("#filter-container");
|
||||
let widget = new CSSFilterEditorWidget(container, "none");
|
||||
// First render
|
||||
yield widget.once("render");
|
||||
|
|
|
@ -48,7 +48,7 @@ add_task(function* () {
|
|||
let [host, win, doc] = yield createHost();
|
||||
|
||||
let xulDocument = win.top.document;
|
||||
let popup = new AutocompletePopup(xulDocument, { autoSelect: true });
|
||||
let popup = new AutocompletePopup({ doc: xulDocument }, { autoSelect: true });
|
||||
yield new Promise(resolve => {
|
||||
createInplaceEditorAndClick({
|
||||
start: runPropertyAutocompletionTest,
|
||||
|
@ -58,6 +58,7 @@ add_task(function* () {
|
|||
}, doc);
|
||||
});
|
||||
|
||||
popup.destroy();
|
||||
host.destroy();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
|
|
@ -49,7 +49,7 @@ add_task(function* () {
|
|||
let [host, win, doc] = yield createHost();
|
||||
|
||||
let xulDocument = win.top.document;
|
||||
let popup = new AutocompletePopup(xulDocument, { autoSelect: true });
|
||||
let popup = new AutocompletePopup({ doc: xulDocument }, { autoSelect: true });
|
||||
|
||||
yield new Promise(resolve => {
|
||||
createInplaceEditorAndClick({
|
||||
|
@ -63,6 +63,7 @@ add_task(function* () {
|
|||
}, doc);
|
||||
});
|
||||
|
||||
popup.destroy();
|
||||
host.destroy();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
|
|
@ -9,6 +9,14 @@ const { InplaceEditor } = require("devtools/client/shared/inplace-editor");
|
|||
const { AutocompletePopup } = require("devtools/client/shared/autocomplete-popup");
|
||||
loadHelperScript("helper_inplace_editor.js");
|
||||
|
||||
const TEST_URI = `data:text/xml;charset=UTF-8,<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/global.css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/common.css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/tooltips.css"?>
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="Tooltip test">
|
||||
</window>`;
|
||||
|
||||
// Test the inplace-editor autocomplete popup is aligned with the completed query.
|
||||
// Which means when completing "style=display:flex; color:" the popup will aim to be
|
||||
// aligned with the ":" next to "color".
|
||||
|
@ -59,10 +67,9 @@ const mockGetCSSValuesForPropertyName = function (propertyName) {
|
|||
|
||||
add_task(function* () {
|
||||
yield addTab("data:text/html;charset=utf-8,inplace editor CSS value autocomplete");
|
||||
let [host, win, doc] = yield createHost();
|
||||
let [host,, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
let xulDocument = win.top.document;
|
||||
let popup = new AutocompletePopup(xulDocument, { autoSelect: true });
|
||||
let popup = new AutocompletePopup({ doc }, { autoSelect: true });
|
||||
|
||||
info("Create a CSS_MIXED type autocomplete");
|
||||
yield new Promise(resolve => {
|
||||
|
@ -75,6 +82,7 @@ add_task(function* () {
|
|||
}, doc);
|
||||
});
|
||||
|
||||
popup.destroy();
|
||||
host.destroy();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
|
|
@ -4,44 +4,42 @@
|
|||
|
||||
// Tests that the spectrum color picker works correctly
|
||||
|
||||
const TEST_URI = "chrome://devtools/content/shared/widgets/spectrum-frame.xhtml";
|
||||
const {Spectrum} = require("devtools/client/shared/widgets/Spectrum");
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
yield performTest();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
const TEST_URI = `data:text/html,
|
||||
<link rel="stylesheet" href="chrome://devtools/content/shared/widgets/spectrum.css" type="text/css"/>
|
||||
<div id="spectrum-container" />`;
|
||||
|
||||
function* performTest() {
|
||||
add_task(function* () {
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
yield testCreateAndDestroyShouldAppendAndRemoveElements(doc);
|
||||
yield testPassingAColorAtInitShouldSetThatColor(doc);
|
||||
yield testSettingAndGettingANewColor(doc);
|
||||
yield testChangingColorShouldEmitEvents(doc);
|
||||
yield testSettingColorShoudUpdateTheUI(doc);
|
||||
let container = doc.getElementById("spectrum-container");
|
||||
|
||||
yield testCreateAndDestroyShouldAppendAndRemoveElements(container);
|
||||
yield testPassingAColorAtInitShouldSetThatColor(container);
|
||||
yield testSettingAndGettingANewColor(container);
|
||||
yield testChangingColorShouldEmitEvents(container);
|
||||
yield testSettingColorShoudUpdateTheUI(container);
|
||||
|
||||
host.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
function testCreateAndDestroyShouldAppendAndRemoveElements(doc) {
|
||||
let containerElement = doc.querySelector("#spectrum");
|
||||
ok(containerElement, "We have the root node to append spectrum to");
|
||||
is(containerElement.childElementCount, 0, "Root node is empty");
|
||||
function testCreateAndDestroyShouldAppendAndRemoveElements(container) {
|
||||
ok(container, "We have the root node to append spectrum to");
|
||||
is(container.childElementCount, 0, "Root node is empty");
|
||||
|
||||
let s = new Spectrum(containerElement, [255, 126, 255, 1]);
|
||||
let s = new Spectrum(container, [255, 126, 255, 1]);
|
||||
s.show();
|
||||
ok(containerElement.childElementCount > 0, "Spectrum has appended elements");
|
||||
ok(container.childElementCount > 0, "Spectrum has appended elements");
|
||||
|
||||
s.destroy();
|
||||
is(containerElement.childElementCount, 0, "Destroying spectrum removed all nodes");
|
||||
is(container.childElementCount, 0, "Destroying spectrum removed all nodes");
|
||||
}
|
||||
|
||||
function testPassingAColorAtInitShouldSetThatColor(doc) {
|
||||
function testPassingAColorAtInitShouldSetThatColor(container) {
|
||||
let initRgba = [255, 126, 255, 1];
|
||||
|
||||
let s = new Spectrum(doc.querySelector("#spectrum"), initRgba);
|
||||
let s = new Spectrum(container, initRgba);
|
||||
s.show();
|
||||
|
||||
let setRgba = s.rgb;
|
||||
|
@ -54,8 +52,8 @@ function testPassingAColorAtInitShouldSetThatColor(doc) {
|
|||
s.destroy();
|
||||
}
|
||||
|
||||
function testSettingAndGettingANewColor(doc) {
|
||||
let s = new Spectrum(doc.querySelector("#spectrum"), [0, 0, 0, 1]);
|
||||
function testSettingAndGettingANewColor(container) {
|
||||
let s = new Spectrum(container, [0, 0, 0, 1]);
|
||||
s.show();
|
||||
|
||||
let colorToSet = [255, 255, 255, 1];
|
||||
|
@ -70,9 +68,9 @@ function testSettingAndGettingANewColor(doc) {
|
|||
s.destroy();
|
||||
}
|
||||
|
||||
function testChangingColorShouldEmitEvents(doc) {
|
||||
function testChangingColorShouldEmitEvents(container) {
|
||||
return new Promise(resolve => {
|
||||
let s = new Spectrum(doc.querySelector("#spectrum"), [255, 255, 255, 1]);
|
||||
let s = new Spectrum(container, [255, 255, 255, 1]);
|
||||
s.show();
|
||||
|
||||
s.once("changed", (event, rgba, color) => {
|
||||
|
@ -92,8 +90,8 @@ function testChangingColorShouldEmitEvents(doc) {
|
|||
});
|
||||
}
|
||||
|
||||
function testSettingColorShoudUpdateTheUI(doc) {
|
||||
let s = new Spectrum(doc.querySelector("#spectrum"), [255, 255, 255, 1]);
|
||||
function testSettingColorShoudUpdateTheUI(container) {
|
||||
let s = new Spectrum(container, [255, 255, 255, 1]);
|
||||
s.show();
|
||||
let dragHelperOriginalPos = [s.dragHelper.style.top, s.dragHelper.style.left];
|
||||
let alphaHelperOriginalPos = s.alphaSliderHelper.style.left;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint no-unused-vars: [2, {"vars": "local", "args": "none"}] */
|
||||
/* import-globals-from head.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
|
@ -8,6 +9,7 @@
|
|||
* Helper methods for the HTMLTooltip integration tests.
|
||||
*/
|
||||
|
||||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const { editableField } = require("devtools/client/shared/inplace-editor");
|
||||
|
||||
/**
|
||||
|
@ -21,8 +23,7 @@ const { editableField } = require("devtools/client/shared/inplace-editor");
|
|||
* @param {String} textContent
|
||||
* (optional) String that will be used as the text content of the span.
|
||||
*/
|
||||
function createInplaceEditorAndClick(options, doc, textContent) {
|
||||
doc.body.innerHTML = "";
|
||||
const createInplaceEditorAndClick = Task.async(function* (options, doc, textContent) {
|
||||
let span = options.element = createSpan(doc);
|
||||
if (textContent) {
|
||||
span.textContent = textContent;
|
||||
|
@ -33,7 +34,7 @@ function createInplaceEditorAndClick(options, doc, textContent) {
|
|||
|
||||
info("Clicking on the inplace-editor field to turn to edit mode");
|
||||
span.click();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Helper to create a span in the provided document.
|
||||
|
@ -44,11 +45,21 @@ function createInplaceEditorAndClick(options, doc, textContent) {
|
|||
*/
|
||||
function createSpan(doc) {
|
||||
info("Creating a new span element");
|
||||
let span = doc.createElement("span");
|
||||
let div = doc.createElementNS(HTML_NS, "div");
|
||||
let span = doc.createElementNS(HTML_NS, "span");
|
||||
span.setAttribute("tabindex", "0");
|
||||
span.style.fontSize = "11px";
|
||||
span.style.display = "inline-block";
|
||||
span.style.width = "100px";
|
||||
span.style.border = "1px solid red";
|
||||
span.style.fontFamily = "monospace";
|
||||
doc.body.appendChild(span);
|
||||
|
||||
div.style.height = "100%";
|
||||
div.style.position = "absolute";
|
||||
div.appendChild(span);
|
||||
|
||||
let parent = doc.querySelector("window") || doc.body;
|
||||
parent.appendChild(div);
|
||||
return span;
|
||||
}
|
||||
|
||||
|
@ -68,8 +79,13 @@ function* testCompletion([key, completion, index, total], editor) {
|
|||
info("Pressing key " + key);
|
||||
info("Expecting " + completion);
|
||||
|
||||
let onSuggest;
|
||||
let onVisibilityChange = null;
|
||||
let open = total > 0;
|
||||
if (editor.popup.isOpen != open) {
|
||||
onVisibilityChange = editor.popup.once(open ? "popup-opened" : "popup-closed");
|
||||
}
|
||||
|
||||
let onSuggest;
|
||||
if (/(left|right|back_space|escape)/ig.test(key)) {
|
||||
info("Adding event listener for right|back_space|escape keys");
|
||||
onSuggest = once(editor.input, "keypress");
|
||||
|
@ -82,17 +98,17 @@ function* testCompletion([key, completion, index, total], editor) {
|
|||
EventUtils.synthesizeKey(key, {}, editor.input.defaultView);
|
||||
|
||||
yield onSuggest;
|
||||
yield onVisibilityChange;
|
||||
yield waitForTick();
|
||||
|
||||
info("Checking the state");
|
||||
if (completion != null) {
|
||||
if (completion !== null) {
|
||||
is(editor.input.value, completion, "Correct value is autocompleted");
|
||||
}
|
||||
if (total === 0) {
|
||||
ok(!(editor.popup && editor.popup.isOpen), "Popup is closed");
|
||||
} else {
|
||||
ok(editor.popup._panel.state == "open" ||
|
||||
editor.popup._panel.state == "showing", "Popup is open");
|
||||
ok(editor.popup.isOpen, "Popup is open");
|
||||
is(editor.popup.getItems().length, total, "Number of suggestions match");
|
||||
is(editor.popup.selectedIndex, index, "Expected item is selected");
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ const {
|
|||
DEFAULT_PRESET_CATEGORY
|
||||
} = require("devtools/client/shared/widgets/CubicBezierPresets");
|
||||
const {getCSSLexer} = require("devtools/shared/css-lexer");
|
||||
const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
/**
|
||||
* CubicBezier data structure helper
|
||||
|
@ -253,26 +254,24 @@ CubicBezierWidget.prototype = {
|
|||
_initMarkup: function () {
|
||||
let doc = this.parent.ownerDocument;
|
||||
|
||||
let wrap = doc.createElement("div");
|
||||
let wrap = doc.createElementNS(XHTML_NS, "div");
|
||||
wrap.className = "display-wrap";
|
||||
|
||||
let plane = doc.createElement("div");
|
||||
let plane = doc.createElementNS(XHTML_NS, "div");
|
||||
plane.className = "coordinate-plane";
|
||||
|
||||
let p1 = doc.createElement("button");
|
||||
let p1 = doc.createElementNS(XHTML_NS, "button");
|
||||
p1.className = "control-point";
|
||||
p1.id = "P1";
|
||||
plane.appendChild(p1);
|
||||
|
||||
let p2 = doc.createElement("button");
|
||||
let p2 = doc.createElementNS(XHTML_NS, "button");
|
||||
p2.className = "control-point";
|
||||
p2.id = "P2";
|
||||
plane.appendChild(p2);
|
||||
|
||||
let curve = doc.createElement("canvas");
|
||||
let curve = doc.createElementNS(XHTML_NS, "canvas");
|
||||
curve.setAttribute("width", 150);
|
||||
curve.setAttribute("height", 370);
|
||||
curve.id = "curve";
|
||||
curve.className = "curve";
|
||||
|
||||
plane.appendChild(curve);
|
||||
wrap.appendChild(plane);
|
||||
|
@ -280,14 +279,14 @@ CubicBezierWidget.prototype = {
|
|||
this.parent.appendChild(wrap);
|
||||
|
||||
return {
|
||||
p1: p1,
|
||||
p2: p2,
|
||||
curve: curve
|
||||
p1,
|
||||
p2,
|
||||
curve
|
||||
};
|
||||
},
|
||||
|
||||
_removeMarkup: function () {
|
||||
this.parent.ownerDocument.querySelector(".display-wrap").remove();
|
||||
this.parent.querySelector(".display-wrap").remove();
|
||||
},
|
||||
|
||||
_initEvents: function () {
|
||||
|
@ -519,13 +518,13 @@ CubicBezierPresetWidget.prototype = {
|
|||
_initMarkup: function () {
|
||||
let doc = this.parent.ownerDocument;
|
||||
|
||||
let presetPane = doc.createElement("div");
|
||||
let presetPane = doc.createElementNS(XHTML_NS, "div");
|
||||
presetPane.className = "preset-pane";
|
||||
|
||||
let categoryList = doc.createElement("div");
|
||||
let categoryList = doc.createElementNS(XHTML_NS, "div");
|
||||
categoryList.id = "preset-categories";
|
||||
|
||||
let presetContainer = doc.createElement("div");
|
||||
let presetContainer = doc.createElementNS(XHTML_NS, "div");
|
||||
presetContainer.id = "preset-container";
|
||||
|
||||
Object.keys(PRESETS).forEach(categoryLabel => {
|
||||
|
@ -554,7 +553,7 @@ CubicBezierPresetWidget.prototype = {
|
|||
_createCategory: function (categoryLabel) {
|
||||
let doc = this.parent.ownerDocument;
|
||||
|
||||
let category = doc.createElement("div");
|
||||
let category = doc.createElementNS(XHTML_NS, "div");
|
||||
category.id = categoryLabel;
|
||||
category.classList.add("category");
|
||||
|
||||
|
@ -572,7 +571,7 @@ CubicBezierPresetWidget.prototype = {
|
|||
_createPresetList: function (categoryLabel) {
|
||||
let doc = this.parent.ownerDocument;
|
||||
|
||||
let presetList = doc.createElement("div");
|
||||
let presetList = doc.createElementNS(XHTML_NS, "div");
|
||||
presetList.id = "preset-category-" + categoryLabel;
|
||||
presetList.classList.add("preset-list");
|
||||
|
||||
|
@ -587,12 +586,12 @@ CubicBezierPresetWidget.prototype = {
|
|||
_createPreset: function (categoryLabel, presetLabel) {
|
||||
let doc = this.parent.ownerDocument;
|
||||
|
||||
let preset = doc.createElement("div");
|
||||
let preset = doc.createElementNS(XHTML_NS, "div");
|
||||
preset.classList.add("preset");
|
||||
preset.id = presetLabel;
|
||||
preset.coordinates = PRESETS[categoryLabel][presetLabel];
|
||||
// Create preset preview
|
||||
let curve = doc.createElement("canvas");
|
||||
let curve = doc.createElementNS(XHTML_NS, "canvas");
|
||||
let bezier = new CubicBezier(preset.coordinates);
|
||||
curve.setAttribute("height", 50);
|
||||
curve.setAttribute("width", 50);
|
||||
|
@ -604,7 +603,7 @@ CubicBezierPresetWidget.prototype = {
|
|||
preset.appendChild(curve);
|
||||
|
||||
// Create preset label
|
||||
let presetLabelElem = doc.createElement("p");
|
||||
let presetLabelElem = doc.createElementNS(XHTML_NS, "p");
|
||||
let presetDisplayLabel = this._normalizePresetLabel(categoryLabel,
|
||||
presetLabel);
|
||||
presetLabelElem.textContent = presetDisplayLabel;
|
||||
|
@ -734,14 +733,14 @@ TimingFunctionPreviewWidget.prototype = {
|
|||
_initMarkup: function () {
|
||||
let doc = this.parent.ownerDocument;
|
||||
|
||||
let container = doc.createElement("div");
|
||||
let container = doc.createElementNS(XHTML_NS, "div");
|
||||
container.className = "timing-function-preview";
|
||||
|
||||
this.dot = doc.createElement("div");
|
||||
this.dot = doc.createElementNS(XHTML_NS, "div");
|
||||
this.dot.className = "dot";
|
||||
container.appendChild(this.dot);
|
||||
|
||||
let scale = doc.createElement("div");
|
||||
let scale = doc.createElementNS(XHTML_NS, "div");
|
||||
scale.className = "scale";
|
||||
container.appendChild(scale);
|
||||
|
||||
|
@ -780,12 +779,17 @@ TimingFunctionPreviewWidget.prototype = {
|
|||
* Re-start the preview animation from the beginning
|
||||
*/
|
||||
restartAnimation: function () {
|
||||
// Reset the animation duration in case it was changed
|
||||
this.dot.style.animationDuration = (this.PREVIEW_DURATION * 2) + "ms";
|
||||
|
||||
// Just toggling the class won't do it unless there's a sync reflow
|
||||
this.dot.classList.remove("animate");
|
||||
this.dot.classList.add("animate");
|
||||
this.dot.animate([
|
||||
{ left: "-7px", offset: 0 },
|
||||
{ left: "143px", offset: 0.25 },
|
||||
{ left: "143px", offset: 0.5 },
|
||||
{ left: "-7px", offset: 0.75 },
|
||||
{ left: "-7px", offset: 1 }
|
||||
], {
|
||||
duration: (this.PREVIEW_DURATION * 2),
|
||||
fill: "forwards"
|
||||
});
|
||||
|
||||
// Restart it again after a while
|
||||
this.autoRestartAnimation = setTimeout(this.restartAnimation.bind(this),
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const { Cc, Ci } = require("chrome");
|
||||
const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
const { LocalizationHelper } = require("devtools/client/shared/l10n");
|
||||
const STRINGS_URI = "chrome://devtools/locale/filterwidget.properties";
|
||||
|
@ -151,6 +152,34 @@ exports.CSSFilterEditorWidget = CSSFilterEditorWidget;
|
|||
|
||||
CSSFilterEditorWidget.prototype = {
|
||||
_initMarkup: function () {
|
||||
let filterListSelectPlaceholder =
|
||||
L10N.getStr("filterListSelectPlaceholder");
|
||||
let addNewFilterButton = L10N.getStr("addNewFilterButton");
|
||||
let presetsToggleButton = L10N.getStr("presetsToggleButton");
|
||||
let newPresetPlaceholder = L10N.getStr("newPresetPlaceholder");
|
||||
let savePresetButton = L10N.getStr("savePresetButton");
|
||||
|
||||
this.el.innerHTML = `
|
||||
<div class="filters-list">
|
||||
<div id="filters"></div>
|
||||
<div class="footer">
|
||||
<select value="">
|
||||
<option value="">${filterListSelectPlaceholder}</option>
|
||||
</select>
|
||||
<button id="add-filter" class="add">${addNewFilterButton}</button>
|
||||
<button id="toggle-presets">${presetsToggleButton}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presets-list">
|
||||
<div id="presets"></div>
|
||||
<div class="footer">
|
||||
<input value="" class="devtools-textinput"
|
||||
placeholder="${newPresetPlaceholder}"></input>
|
||||
<button class="add">${savePresetButton}</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
this.filtersList = this.el.querySelector("#filters");
|
||||
this.presetsList = this.el.querySelector("#presets");
|
||||
this.togglePresets = this.el.querySelector("#toggle-presets");
|
||||
|
@ -183,7 +212,7 @@ CSSFilterEditorWidget.prototype = {
|
|||
_populateFilterSelect: function () {
|
||||
let select = this.filterSelect;
|
||||
filterList.forEach(filter => {
|
||||
let option = this.doc.createElement("option");
|
||||
let option = this.doc.createElementNS(XHTML_NS, "option");
|
||||
option.innerHTML = option.value = filter.name;
|
||||
select.appendChild(option);
|
||||
});
|
||||
|
@ -193,31 +222,31 @@ CSSFilterEditorWidget.prototype = {
|
|||
* Creates a template for filter elements which is cloned and used in render
|
||||
*/
|
||||
_buildFilterItemMarkup: function () {
|
||||
let base = this.doc.createElement("div");
|
||||
let base = this.doc.createElementNS(XHTML_NS, "div");
|
||||
base.className = "filter";
|
||||
|
||||
let name = this.doc.createElement("div");
|
||||
let name = this.doc.createElementNS(XHTML_NS, "div");
|
||||
name.className = "filter-name";
|
||||
|
||||
let value = this.doc.createElement("div");
|
||||
let value = this.doc.createElementNS(XHTML_NS, "div");
|
||||
value.className = "filter-value";
|
||||
|
||||
let drag = this.doc.createElement("i");
|
||||
let drag = this.doc.createElementNS(XHTML_NS, "i");
|
||||
drag.title = L10N.getStr("dragHandleTooltipText");
|
||||
|
||||
let label = this.doc.createElement("label");
|
||||
let label = this.doc.createElementNS(XHTML_NS, "label");
|
||||
|
||||
name.appendChild(drag);
|
||||
name.appendChild(label);
|
||||
|
||||
let unitPreview = this.doc.createElement("span");
|
||||
let input = this.doc.createElement("input");
|
||||
let unitPreview = this.doc.createElementNS(XHTML_NS, "span");
|
||||
let input = this.doc.createElementNS(XHTML_NS, "input");
|
||||
input.classList.add("devtools-textinput");
|
||||
|
||||
value.appendChild(input);
|
||||
value.appendChild(unitPreview);
|
||||
|
||||
let removeButton = this.doc.createElement("button");
|
||||
let removeButton = this.doc.createElementNS(XHTML_NS, "button");
|
||||
removeButton.className = "remove-button";
|
||||
|
||||
base.appendChild(name);
|
||||
|
@ -228,16 +257,16 @@ CSSFilterEditorWidget.prototype = {
|
|||
},
|
||||
|
||||
_buildPresetItemMarkup: function () {
|
||||
let base = this.doc.createElement("div");
|
||||
let base = this.doc.createElementNS(XHTML_NS, "div");
|
||||
base.classList.add("preset");
|
||||
|
||||
let name = this.doc.createElement("label");
|
||||
let name = this.doc.createElementNS(XHTML_NS, "label");
|
||||
base.appendChild(name);
|
||||
|
||||
let value = this.doc.createElement("span");
|
||||
let value = this.doc.createElementNS(XHTML_NS, "span");
|
||||
base.appendChild(value);
|
||||
|
||||
let removeButton = this.doc.createElement("button");
|
||||
let removeButton = this.doc.createElementNS(XHTML_NS, "button");
|
||||
removeButton.classList.add("remove-button");
|
||||
|
||||
base.appendChild(removeButton);
|
||||
|
@ -659,6 +688,11 @@ CSSFilterEditorWidget.prototype = {
|
|||
|
||||
renderPresets: function () {
|
||||
this.getPresets().then(presets => {
|
||||
// getPresets is async and the widget may be destroyed in between.
|
||||
if (!this.presetsList) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!presets || !presets.length) {
|
||||
this.presetsList.innerHTML = `<p>${L10N.getStr("emptyPresetList")}</p>`;
|
||||
this.emit("render");
|
||||
|
|
|
@ -195,12 +195,15 @@ const getRelativeRect = function (node, relativeTo) {
|
|||
* - {Boolean} useXulWrapper
|
||||
* Defaults to false. If the tooltip is hosted in a XUL document, use a XUL panel
|
||||
* in order to use all the screen viewport available.
|
||||
* - {String} stylesheet
|
||||
* Style sheet URL to apply to the tooltip content.
|
||||
*/
|
||||
function HTMLTooltip(toolbox, {
|
||||
type = "normal",
|
||||
autofocus = false,
|
||||
consumeOutsideClicks = true,
|
||||
useXulWrapper = false,
|
||||
stylesheet = "",
|
||||
} = {}) {
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
|
@ -223,6 +226,9 @@ function HTMLTooltip(toolbox, {
|
|||
|
||||
this.container = this._createContainer();
|
||||
|
||||
if (stylesheet) {
|
||||
this._applyStylesheet(stylesheet);
|
||||
}
|
||||
if (this._isXUL() && this.useXulWrapper) {
|
||||
// When using a XUL panel as the wrapper, the actual markup for the tooltip is as
|
||||
// follows :
|
||||
|
@ -420,6 +426,7 @@ HTMLTooltip.prototype = {
|
|||
hide: Task.async(function* () {
|
||||
this.doc.defaultView.clearTimeout(this.attachEventsTimer);
|
||||
if (!this.isVisible()) {
|
||||
this.emit("hidden");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -500,7 +507,7 @@ HTMLTooltip.prototype = {
|
|||
}
|
||||
|
||||
// Check if the node window is in the tooltip container.
|
||||
while (win.parent && win.parent != win) {
|
||||
while (win.parent && win.parent !== win) {
|
||||
if (win.parent === tooltipWindow) {
|
||||
// If the parent window is the tooltip window, check if the tooltip contains
|
||||
// the current frame element.
|
||||
|
@ -573,4 +580,16 @@ HTMLTooltip.prototype = {
|
|||
top += this.doc.defaultView.mozInnerScreenY;
|
||||
return {top, right: left + width, bottom: top + height, left, width, height};
|
||||
},
|
||||
|
||||
/**
|
||||
* Apply a scoped stylesheet to the container so that this css file only
|
||||
* applies to it.
|
||||
*/
|
||||
_applyStylesheet: function (url) {
|
||||
let style = this.doc.createElementNS(XHTML_NS, "style");
|
||||
style.setAttribute("scoped", "true");
|
||||
url = url.replace(/"/g, "\\\"");
|
||||
style.textContent = `@import url("${url}");`;
|
||||
this.container.appendChild(style);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"use strict";
|
||||
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
/**
|
||||
* Spectrum creates a color picker widget in any container you give it.
|
||||
|
@ -32,7 +33,7 @@ const EventEmitter = require("devtools/shared/event-emitter");
|
|||
function Spectrum(parentEl, rgb) {
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
this.element = parentEl.ownerDocument.createElement("div");
|
||||
this.element = parentEl.ownerDocument.createElementNS(XHTML_NS, "div");
|
||||
this.parentEl = parentEl;
|
||||
|
||||
this.element.className = "spectrum-container";
|
||||
|
@ -131,21 +132,6 @@ Spectrum.rgbToHsv = function (r, g, b, a) {
|
|||
return [h, s, v, a];
|
||||
};
|
||||
|
||||
Spectrum.getOffset = function (el) {
|
||||
let curleft = 0, curtop = 0;
|
||||
if (el.offsetParent) {
|
||||
while (el) {
|
||||
curleft += el.offsetLeft;
|
||||
curtop += el.offsetTop;
|
||||
el = el.offsetParent;
|
||||
}
|
||||
}
|
||||
return {
|
||||
left: curleft,
|
||||
top: curtop
|
||||
};
|
||||
};
|
||||
|
||||
Spectrum.draggable = function (element, onmove, onstart, onstop) {
|
||||
onmove = onmove || function () {};
|
||||
onstart = onstart || function () {};
|
||||
|
@ -188,7 +174,7 @@ Spectrum.draggable = function (element, onmove, onstart, onstop) {
|
|||
maxHeight = element.offsetHeight;
|
||||
maxWidth = element.offsetWidth;
|
||||
|
||||
offset = Spectrum.getOffset(element);
|
||||
offset = element.getBoundingClientRect();
|
||||
|
||||
move(e);
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ const {Eyedropper} = require("devtools/client/eyedropper/eyedropper");
|
|||
const {gDevTools} = require("devtools/client/framework/devtools");
|
||||
const Services = require("Services");
|
||||
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||
const {HTMLTooltip} = require("devtools/client/shared/widgets/HTMLTooltip");
|
||||
const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
|
||||
|
||||
loader.lazyRequireGetter(this, "beautify", "devtools/shared/jsbeautify/beautify");
|
||||
loader.lazyRequireGetter(this, "setNamedTimeout", "devtools/client/shared/widgets/view-helpers", true);
|
||||
|
@ -31,11 +33,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "VariablesViewController",
|
|||
"resource://devtools/client/shared/widgets/VariablesViewController.jsm");
|
||||
|
||||
const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const SPECTRUM_FRAME = "chrome://devtools/content/shared/widgets/spectrum-frame.xhtml";
|
||||
const CUBIC_BEZIER_FRAME =
|
||||
"chrome://devtools/content/shared/widgets/cubic-bezier-frame.xhtml";
|
||||
const MDN_DOCS_FRAME = "chrome://devtools/content/shared/widgets/mdn-docs-frame.xhtml";
|
||||
const FILTER_FRAME = "chrome://devtools/content/shared/widgets/filter-frame.xhtml";
|
||||
const ESCAPE_KEYCODE = Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE;
|
||||
const RETURN_KEYCODE = Ci.nsIDOMKeyEvent.DOM_VK_RETURN;
|
||||
const POPUP_EVENTS = ["shown", "hidden", "showing", "hiding"];
|
||||
|
@ -557,99 +555,6 @@ Tooltip.prototype = {
|
|||
return def.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Fill the tooltip with a new instance of the spectrum color picker widget
|
||||
* initialized with the given color, and return a promise that resolves to
|
||||
* the instance of spectrum
|
||||
*/
|
||||
setColorPickerContent: function (color) {
|
||||
let dimensions = {width: "210", height: "216"};
|
||||
let panel = this.panel;
|
||||
return this.setIFrameContent(dimensions, SPECTRUM_FRAME).then(onLoaded);
|
||||
|
||||
function onLoaded(iframe) {
|
||||
let win = iframe.contentWindow.wrappedJSObject;
|
||||
let def = defer();
|
||||
let container = win.document.getElementById("spectrum");
|
||||
let spectrum = new Spectrum(container, color);
|
||||
|
||||
function finalizeSpectrum() {
|
||||
spectrum.show();
|
||||
def.resolve(spectrum);
|
||||
}
|
||||
|
||||
// Finalize spectrum's init when the tooltip becomes visible
|
||||
if (panel.state == "open") {
|
||||
finalizeSpectrum();
|
||||
} else {
|
||||
panel.addEventListener("popupshown", function shown() {
|
||||
panel.removeEventListener("popupshown", shown, true);
|
||||
finalizeSpectrum();
|
||||
}, true);
|
||||
}
|
||||
return def.promise;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fill the tooltip with a new instance of the cubic-bezier widget
|
||||
* initialized with the given value, and return a promise that resolves to
|
||||
* the instance of the widget
|
||||
*/
|
||||
setCubicBezierContent: function (bezier) {
|
||||
let dimensions = {width: "500", height: "360"};
|
||||
let panel = this.panel;
|
||||
return this.setIFrameContent(dimensions, CUBIC_BEZIER_FRAME).then(onLoaded);
|
||||
|
||||
function onLoaded(iframe) {
|
||||
let win = iframe.contentWindow.wrappedJSObject;
|
||||
let def = defer();
|
||||
let container = win.document.getElementById("container");
|
||||
let widget = new CubicBezierWidget(container, bezier);
|
||||
|
||||
// Resolve to the widget instance whenever the popup becomes visible
|
||||
if (panel.state == "open") {
|
||||
def.resolve(widget);
|
||||
} else {
|
||||
panel.addEventListener("popupshown", function shown() {
|
||||
panel.removeEventListener("popupshown", shown, true);
|
||||
def.resolve(widget);
|
||||
}, true);
|
||||
}
|
||||
return def.promise;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fill the tooltip with a new instance of the CSSFilterEditorWidget
|
||||
* widget initialized with the given filter value, and return a promise
|
||||
* that resolves to the instance of the widget when ready.
|
||||
*/
|
||||
setFilterContent: function (filter) {
|
||||
let dimensions = {width: "500", height: "200"};
|
||||
let panel = this.panel;
|
||||
|
||||
return this.setIFrameContent(dimensions, FILTER_FRAME).then(onLoaded);
|
||||
|
||||
function onLoaded(iframe) {
|
||||
let win = iframe.contentWindow.wrappedJSObject;
|
||||
let def = defer();
|
||||
let container = win.document.getElementById("container");
|
||||
let widget = new CSSFilterEditorWidget(container, filter);
|
||||
|
||||
// Resolve to the widget instance whenever the popup becomes visible
|
||||
if (panel.state === "open") {
|
||||
def.resolve(widget);
|
||||
} else {
|
||||
panel.addEventListener("popupshown", function shown() {
|
||||
panel.removeEventListener("popupshown", shown, true);
|
||||
def.resolve(widget);
|
||||
}, true);
|
||||
}
|
||||
return def.promise;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the content of this tooltip to the MDN docs widget.
|
||||
*
|
||||
|
@ -681,29 +586,44 @@ Tooltip.prototype = {
|
|||
* Base class for all (color, gradient, ...)-swatch based value editors inside
|
||||
* tooltips
|
||||
*
|
||||
* @param {XULDocument} doc
|
||||
* @param {Toolbox} toolbox
|
||||
* The devtools toolbox, needed to get the devtools main window.
|
||||
*/
|
||||
function SwatchBasedEditorTooltip(doc) {
|
||||
function SwatchBasedEditorTooltip(toolbox, stylesheet) {
|
||||
// Creating a tooltip instance
|
||||
// This one will consume outside clicks as it makes more sense to let the user
|
||||
// close the tooltip by clicking out
|
||||
// It will also close on <escape> and <enter>
|
||||
this.tooltip = new Tooltip(doc, {
|
||||
consumeOutsideClick: true,
|
||||
closeOnKeys: [ESCAPE_KEYCODE, RETURN_KEYCODE],
|
||||
noAutoFocus: false
|
||||
this.tooltip = new HTMLTooltip(toolbox, {
|
||||
type: "arrow",
|
||||
consumeOutsideClicks: true,
|
||||
useXulWrapper: true,
|
||||
stylesheet
|
||||
});
|
||||
|
||||
// By default, swatch-based editor tooltips revert value change on <esc> and
|
||||
// commit value change on <enter>
|
||||
this._onTooltipKeypress = (event, code) => {
|
||||
if (code === ESCAPE_KEYCODE) {
|
||||
this.revert();
|
||||
} else if (code === RETURN_KEYCODE) {
|
||||
this.commit();
|
||||
this.shortcuts = new KeyShortcuts({
|
||||
window: this.tooltip.topWindow
|
||||
});
|
||||
this.shortcuts.on("Escape", (name, event) => {
|
||||
if (!this.tooltip.isVisible()) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
this.tooltip.on("keypress", this._onTooltipKeypress);
|
||||
this.revert();
|
||||
this.hide();
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
});
|
||||
this.shortcuts.on("Return", (name, event) => {
|
||||
if (!this.tooltip.isVisible()) {
|
||||
return;
|
||||
}
|
||||
this.commit();
|
||||
this.hide();
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
// All target swatches are kept in a map, indexed by swatch DOM elements
|
||||
this.swatches = new Map();
|
||||
|
@ -722,18 +642,14 @@ SwatchBasedEditorTooltip.prototype = {
|
|||
this.tooltip.show(this.activeSwatch, "topcenter bottomleft");
|
||||
|
||||
// When the tooltip is closed by clicking outside the panel we want to
|
||||
// commit any changes. Because the "hidden" event destroys the tooltip we
|
||||
// need to do this before the tooltip is destroyed (in the "hiding"
|
||||
// event).
|
||||
this.tooltip.once("hiding", () => {
|
||||
// commit any changes.
|
||||
this.tooltip.once("hidden", () => {
|
||||
if (!this._reverted && !this.eyedropperOpen) {
|
||||
this.commit();
|
||||
}
|
||||
this._reverted = false;
|
||||
});
|
||||
|
||||
// Once the tooltip is hidden we need to clean up any remaining objects.
|
||||
this.tooltip.once("hidden", () => {
|
||||
// Once the tooltip is hidden we need to clean up any remaining objects.
|
||||
if (!this.eyedropperOpen) {
|
||||
this.activeSwatch = null;
|
||||
}
|
||||
|
@ -825,7 +741,7 @@ SwatchBasedEditorTooltip.prototype = {
|
|||
if (this.activeSwatch) {
|
||||
this._reverted = true;
|
||||
let swatch = this.swatches.get(this.activeSwatch);
|
||||
this.tooltip.once("hiding", () => {
|
||||
this.tooltip.once("hidden", () => {
|
||||
swatch.callbacks.onRevert();
|
||||
});
|
||||
}
|
||||
|
@ -846,6 +762,7 @@ SwatchBasedEditorTooltip.prototype = {
|
|||
this.activeSwatch = null;
|
||||
this.tooltip.off("keypress", this._onTooltipKeypress);
|
||||
this.tooltip.destroy();
|
||||
this.shortcuts.destroy();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -856,14 +773,16 @@ SwatchBasedEditorTooltip.prototype = {
|
|||
* It just wraps a standard Tooltip and sets its content with an instance of a
|
||||
* color picker.
|
||||
*
|
||||
* @param {XULDocument} doc
|
||||
* @param {Toolbox} toolbox
|
||||
* The devtools toolbox, needed to get the devtools main window.
|
||||
*/
|
||||
function SwatchColorPickerTooltip(doc) {
|
||||
SwatchBasedEditorTooltip.call(this, doc);
|
||||
function SwatchColorPickerTooltip(toolbox) {
|
||||
let stylesheet = "chrome://devtools/content/shared/widgets/spectrum.css";
|
||||
SwatchBasedEditorTooltip.call(this, toolbox, stylesheet);
|
||||
|
||||
// Creating a spectrum instance. this.spectrum will always be a promise that
|
||||
// resolves to the spectrum instance
|
||||
this.spectrum = this.tooltip.setColorPickerContent([0, 0, 0, 1]);
|
||||
this.spectrum = this.setColorPickerContent([0, 0, 0, 1]);
|
||||
this._onSpectrumColorChange = this._onSpectrumColorChange.bind(this);
|
||||
this._openEyeDropper = this._openEyeDropper.bind(this);
|
||||
}
|
||||
|
@ -872,6 +791,36 @@ module.exports.SwatchColorPickerTooltip = SwatchColorPickerTooltip;
|
|||
|
||||
SwatchColorPickerTooltip.prototype =
|
||||
Heritage.extend(SwatchBasedEditorTooltip.prototype, {
|
||||
/**
|
||||
* Fill the tooltip with a new instance of the spectrum color picker widget
|
||||
* initialized with the given color, and return the instance of spectrum
|
||||
*/
|
||||
setColorPickerContent: function (color) {
|
||||
let { doc } = this.tooltip;
|
||||
|
||||
let container = doc.createElementNS(XHTML_NS, "div");
|
||||
container.id = "spectrum-tooltip";
|
||||
let spectrumNode = doc.createElementNS(XHTML_NS, "div");
|
||||
spectrumNode.id = "spectrum";
|
||||
container.appendChild(spectrumNode);
|
||||
let eyedropper = doc.createElementNS(XHTML_NS, "button");
|
||||
eyedropper.id = "eyedropper-button";
|
||||
eyedropper.className = "devtools-button";
|
||||
container.appendChild(eyedropper);
|
||||
|
||||
this.tooltip.setContent(container, { width: 210, height: 216 });
|
||||
|
||||
let spectrum = new Spectrum(spectrumNode, color);
|
||||
|
||||
// Wait for the tooltip to be shown before calling spectrum.show
|
||||
// as it expect to be visible in order to compute DOM element sizes.
|
||||
this.tooltip.once("shown", () => {
|
||||
spectrum.show();
|
||||
});
|
||||
|
||||
return spectrum;
|
||||
},
|
||||
|
||||
/**
|
||||
* Overriding the SwatchBasedEditorTooltip.show function to set spectrum's
|
||||
* color.
|
||||
|
@ -884,16 +833,13 @@ Heritage.extend(SwatchBasedEditorTooltip.prototype, {
|
|||
this.currentSwatchColor = this.activeSwatch.nextSibling;
|
||||
this._originalColor = this.currentSwatchColor.textContent;
|
||||
let color = this.activeSwatch.style.backgroundColor;
|
||||
this.spectrum.then(spectrum => {
|
||||
spectrum.off("changed", this._onSpectrumColorChange);
|
||||
spectrum.rgb = this._colorToRgba(color);
|
||||
spectrum.on("changed", this._onSpectrumColorChange);
|
||||
spectrum.updateUI();
|
||||
});
|
||||
this.spectrum.off("changed", this._onSpectrumColorChange);
|
||||
this.spectrum.rgb = this._colorToRgba(color);
|
||||
this.spectrum.on("changed", this._onSpectrumColorChange);
|
||||
this.spectrum.updateUI();
|
||||
}
|
||||
|
||||
let tooltipDoc = this.tooltip.content.contentDocument;
|
||||
let eyeButton = tooltipDoc.querySelector("#eyedropper-button");
|
||||
let eyeButton = this.tooltip.doc.querySelector("#eyedropper-button");
|
||||
eyeButton.addEventListener("click", this._openEyeDropper);
|
||||
},
|
||||
|
||||
|
@ -967,10 +913,8 @@ Heritage.extend(SwatchBasedEditorTooltip.prototype, {
|
|||
destroy: function () {
|
||||
SwatchBasedEditorTooltip.prototype.destroy.call(this);
|
||||
this.currentSwatchColor = null;
|
||||
this.spectrum.then(spectrum => {
|
||||
spectrum.off("changed", this._onSpectrumColorChange);
|
||||
spectrum.destroy();
|
||||
});
|
||||
this.spectrum.off("changed", this._onSpectrumColorChange);
|
||||
this.spectrum.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -981,14 +925,16 @@ Heritage.extend(SwatchBasedEditorTooltip.prototype, {
|
|||
* It just wraps a standard Tooltip and sets its content with an instance of a
|
||||
* CubicBezierWidget.
|
||||
*
|
||||
* @param {XULDocument} doc
|
||||
* @param {Toolbox} toolbox
|
||||
* The devtools toolbox, needed to get the devtools main window.
|
||||
*/
|
||||
function SwatchCubicBezierTooltip(doc) {
|
||||
SwatchBasedEditorTooltip.call(this, doc);
|
||||
function SwatchCubicBezierTooltip(toolbox) {
|
||||
let stylesheet = "chrome://devtools/content/shared/widgets/cubic-bezier.css";
|
||||
SwatchBasedEditorTooltip.call(this, toolbox, stylesheet);
|
||||
|
||||
// Creating a cubic-bezier instance.
|
||||
// this.widget will always be a promise that resolves to the widget instance
|
||||
this.widget = this.tooltip.setCubicBezierContent([0, 0, 1, 1]);
|
||||
this.widget = this.setCubicBezierContent([0, 0, 1, 1]);
|
||||
this._onUpdate = this._onUpdate.bind(this);
|
||||
}
|
||||
|
||||
|
@ -996,6 +942,31 @@ module.exports.SwatchCubicBezierTooltip = SwatchCubicBezierTooltip;
|
|||
|
||||
SwatchCubicBezierTooltip.prototype =
|
||||
Heritage.extend(SwatchBasedEditorTooltip.prototype, {
|
||||
/**
|
||||
* Fill the tooltip with a new instance of the cubic-bezier widget
|
||||
* initialized with the given value, and return a promise that resolves to
|
||||
* the instance of the widget
|
||||
*/
|
||||
setCubicBezierContent: function (bezier) {
|
||||
let { doc } = this.tooltip;
|
||||
|
||||
let container = doc.createElementNS(XHTML_NS, "div");
|
||||
container.className = "cubic-bezier-container";
|
||||
|
||||
this.tooltip.setContent(container, { width: 510, height: 370 });
|
||||
|
||||
let def = defer();
|
||||
|
||||
// Wait for the tooltip to be shown before calling instanciating the widget
|
||||
// as it expect its DOM elements to be visible.
|
||||
this.tooltip.once("shown", () => {
|
||||
let widget = new CubicBezierWidget(container, bezier);
|
||||
def.resolve(widget);
|
||||
});
|
||||
|
||||
return def.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Overriding the SwatchBasedEditorTooltip.show function to set the cubic
|
||||
* bezier curve in the widget
|
||||
|
@ -1079,14 +1050,15 @@ CssDocsTooltip.prototype = {
|
|||
* It just wraps a standard Tooltip and sets its content with an instance of a
|
||||
* CSSFilterEditorWidget.
|
||||
*
|
||||
* @param {XULDocument} doc
|
||||
* @param {Toolbox} toolbox
|
||||
* The devtools toolbox, needed to get the devtools main window.
|
||||
*/
|
||||
function SwatchFilterTooltip(doc) {
|
||||
SwatchBasedEditorTooltip.call(this, doc);
|
||||
function SwatchFilterTooltip(toolbox) {
|
||||
let stylesheet = "chrome://devtools/content/shared/widgets/filter-widget.css";
|
||||
SwatchBasedEditorTooltip.call(this, toolbox, stylesheet);
|
||||
|
||||
// Creating a filter editor instance.
|
||||
// this.widget will always be a promise that resolves to the widget instance
|
||||
this.widget = this.tooltip.setFilterContent("none");
|
||||
this.widget = this.setFilterContent("none");
|
||||
this._onUpdate = this._onUpdate.bind(this);
|
||||
}
|
||||
|
||||
|
@ -1094,18 +1066,32 @@ exports.SwatchFilterTooltip = SwatchFilterTooltip;
|
|||
|
||||
SwatchFilterTooltip.prototype =
|
||||
Heritage.extend(SwatchBasedEditorTooltip.prototype, {
|
||||
/**
|
||||
* Fill the tooltip with a new instance of the CSSFilterEditorWidget
|
||||
* widget initialized with the given filter value, and return a promise
|
||||
* that resolves to the instance of the widget when ready.
|
||||
*/
|
||||
setFilterContent: function (filter) {
|
||||
let { doc } = this.tooltip;
|
||||
|
||||
let container = doc.createElementNS(XHTML_NS, "div");
|
||||
container.id = "filter-container";
|
||||
|
||||
this.tooltip.setContent(container, { width: 510, height: 200 });
|
||||
|
||||
return new CSSFilterEditorWidget(container, filter);
|
||||
},
|
||||
|
||||
show: function () {
|
||||
// Call the parent class' show function
|
||||
SwatchBasedEditorTooltip.prototype.show.call(this);
|
||||
// Then set the filter value and listen to changes to preview them
|
||||
if (this.activeSwatch) {
|
||||
this.currentFilterValue = this.activeSwatch.nextSibling;
|
||||
this.widget.then(widget => {
|
||||
widget.off("updated", this._onUpdate);
|
||||
widget.on("updated", this._onUpdate);
|
||||
widget.setCssValue(this.currentFilterValue.textContent);
|
||||
widget.render();
|
||||
});
|
||||
this.widget.off("updated", this._onUpdate);
|
||||
this.widget.on("updated", this._onUpdate);
|
||||
this.widget.setCssValue(this.currentFilterValue.textContent);
|
||||
this.widget.render();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1128,10 +1114,8 @@ Heritage.extend(SwatchBasedEditorTooltip.prototype, {
|
|||
destroy: function () {
|
||||
SwatchBasedEditorTooltip.prototype.destroy.call(this);
|
||||
this.currentFilterValue = null;
|
||||
this.widget.then(widget => {
|
||||
widget.off("updated", this._onUpdate);
|
||||
widget.destroy();
|
||||
});
|
||||
this.widget.off("updated", this._onUpdate);
|
||||
this.widget.destroy();
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/content/shared/widgets/cubic-bezier.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://devtools/content/shared/theme-switching.js"/>
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
width: 500px;
|
||||
height: 370px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body role="application">
|
||||
<div id="container"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -5,12 +5,13 @@
|
|||
/* Based on Lea Verou www.cubic-bezier.com
|
||||
See https://github.com/LeaVerou/cubic-bezier */
|
||||
|
||||
#container {
|
||||
.cubic-bezier-container {
|
||||
display: flex;
|
||||
width: 500px;
|
||||
height: 370px;
|
||||
flex-direction: row-reverse;
|
||||
overflow: hidden;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.display-wrap {
|
||||
|
@ -64,13 +65,13 @@
|
|||
|
||||
-moz-user-select: none;
|
||||
}
|
||||
canvas#curve {
|
||||
canvas.curve {
|
||||
background: linear-gradient(-45deg, transparent 49.7%, rgba(0,0,0,.2) 49.7%, rgba(0,0,0,.2) 50.3%, transparent 50.3%) center no-repeat;
|
||||
background-size: 100% 100%;
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
.theme-dark canvas#curve {
|
||||
.theme-dark canvas.curve {
|
||||
background: linear-gradient(-45deg, transparent 49.7%, #eee 49.7%, #eee 50.3%, transparent 50.3%) center no-repeat;
|
||||
}
|
||||
|
||||
|
@ -109,30 +110,6 @@ canvas#curve {
|
|||
background: #4C9ED9;
|
||||
}
|
||||
|
||||
.timing-function-preview .dot.animate {
|
||||
animation-duration: 2.5s;
|
||||
animation-fill-mode: forwards;
|
||||
animation-name: timing-function-preview;
|
||||
}
|
||||
|
||||
@keyframes timing-function-preview {
|
||||
0% {
|
||||
left: -7px;
|
||||
}
|
||||
33% {
|
||||
left: 143px;
|
||||
}
|
||||
50% {
|
||||
left: 143px;
|
||||
}
|
||||
83% {
|
||||
left: -7px;
|
||||
}
|
||||
100% {
|
||||
left: -7px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Preset Widget */
|
||||
|
||||
.preset-pane {
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % filterwidgetDTD SYSTEM "chrome://devtools/locale/filterwidget.dtd" >
|
||||
%filterwidgetDTD;
|
||||
]>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/content/shared/widgets/filter-widget.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://devtools/content/shared/theme-switching.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="container">
|
||||
<div class="filters-list">
|
||||
<div id="filters"></div>
|
||||
<div class="footer">
|
||||
<select value="">
|
||||
<option value="">&filterListSelectPlaceholder;</option>
|
||||
</select>
|
||||
<button id="add-filter" class="add">&addNewFilterButton;</button>
|
||||
<button id="toggle-presets">&presetsToggleButton;</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presets-list">
|
||||
<div id="presets"></div>
|
||||
<div class="footer">
|
||||
<input value="" class="devtools-textinput"
|
||||
placeholder="&newPresetPlaceholder;"></input>
|
||||
<button class="add">&savePresetButton;</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -2,23 +2,18 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
font: message-box;
|
||||
color: var(--theme-body-color);
|
||||
}
|
||||
|
||||
/* Main container: Displays the filters and presets in 2 columns */
|
||||
|
||||
#container {
|
||||
#filter-container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
position: relative;
|
||||
padding: 5px;
|
||||
/* when opened in a xul:panel, a gray color is applied to text */
|
||||
color: var(--theme-body-color);
|
||||
}
|
||||
|
||||
#container.dragging {
|
||||
#filter-container.dragging {
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
|
@ -49,13 +44,13 @@ html, body {
|
|||
margin-top: 4px;
|
||||
}
|
||||
|
||||
#container:not(.show-presets) .presets-list {
|
||||
#filter-container:not(.show-presets) .presets-list {
|
||||
width: 0;
|
||||
border-left: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
#container.show-presets .filters-list {
|
||||
#filter-container.show-presets .filters-list {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
|
@ -211,14 +206,14 @@ input {
|
|||
display: none !important;
|
||||
}
|
||||
|
||||
#container .dragging {
|
||||
#filter-container .dragging {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
/* message shown when there's no filter specified */
|
||||
#container p {
|
||||
#filter-container p {
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/spectrum.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://devtools/content/shared/theme-switching.js"/>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body role="application">
|
||||
<div id="spectrum"></div>
|
||||
<button id="eyedropper-button" class="devtools-button"></button>
|
||||
</body>
|
||||
</html>
|
|
@ -5,11 +5,8 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { Cu } = require("chrome");
|
||||
const CSSCompleter =
|
||||
require("devtools/client/sourceeditor/css-autocompleter");
|
||||
const { AutocompletePopup } =
|
||||
require("devtools/client/shared/autocomplete-popup");
|
||||
const CSSCompleter = require("devtools/client/sourceeditor/css-autocompleter");
|
||||
const { AutocompletePopup } = require("devtools/client/shared/autocomplete-popup");
|
||||
|
||||
const CM_TERN_SCRIPTS = [
|
||||
"chrome://devtools/content/sourceeditor/codemirror/addon/tern/tern.js",
|
||||
|
@ -18,9 +15,6 @@ const CM_TERN_SCRIPTS = [
|
|||
|
||||
const autocompleteMap = new WeakMap();
|
||||
|
||||
// A simple way to give each popup its own panelId.
|
||||
let autocompleteCounter = 0;
|
||||
|
||||
/**
|
||||
* Prepares an editor instance for autocompletion.
|
||||
*/
|
||||
|
@ -124,23 +118,21 @@ function initializeAutoCompletion(ctx, options = {}) {
|
|||
insertPopupItem(ed, popup.selectedItem);
|
||||
}
|
||||
|
||||
popup.once("popup-closed", () => {
|
||||
// This event is used in tests.
|
||||
ed.emit("popup-hidden");
|
||||
});
|
||||
popup.hidePopup();
|
||||
// This event is used in tests.
|
||||
ed.emit("popup-hidden");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Give each popup a new name to avoid sharing the elements.
|
||||
let panelId = "devtools_sourceEditorCompletePopup" + autocompleteCounter;
|
||||
++autocompleteCounter;
|
||||
|
||||
let popup = new AutocompletePopup(win.parent.document, {
|
||||
position: "after_start",
|
||||
fixedWidth: true,
|
||||
let popup = new AutocompletePopup({ doc: win.parent.document }, {
|
||||
position: "bottom",
|
||||
theme: "auto",
|
||||
autoSelect: true,
|
||||
onClick: insertSelectedPopupItem,
|
||||
panelId: panelId
|
||||
onClick: insertSelectedPopupItem
|
||||
});
|
||||
|
||||
let cycle = reverse => {
|
||||
|
@ -217,30 +209,33 @@ function autoComplete({ ed, cm }) {
|
|||
return;
|
||||
}
|
||||
let cur = ed.getCursor();
|
||||
completer.complete(cm.getRange({line: 0, ch: 0}, cur), cur)
|
||||
.then(suggestions => {
|
||||
if (!suggestions || !suggestions.length ||
|
||||
suggestions[0].preLabel == null) {
|
||||
autocompleteOpts.suggestionInsertedOnce = false;
|
||||
popup.hidePopup();
|
||||
ed.emit("after-suggest");
|
||||
return;
|
||||
}
|
||||
// The cursor is at the end of the currently entered part of the token,
|
||||
// like "backgr|" but we need to open the popup at the beginning of the
|
||||
// character "b". Thus we need to calculate the width of the entered part
|
||||
// of the token ("backgr" here). 4 comes from the popup's left padding.
|
||||
|
||||
let cursorElement =
|
||||
cm.display.cursorDiv.querySelector(".CodeMirror-cursor");
|
||||
let left = suggestions[0].preLabel.length * cm.defaultCharWidth() + 4;
|
||||
popup.hidePopup();
|
||||
popup.setItems(suggestions);
|
||||
popup.openPopup(cursorElement, -1 * left, 0);
|
||||
completer.complete(cm.getRange({line: 0, ch: 0}, cur), cur).then(suggestions => {
|
||||
if (!suggestions || !suggestions.length || suggestions[0].preLabel == null) {
|
||||
autocompleteOpts.suggestionInsertedOnce = false;
|
||||
popup.once("popup-closed", () => {
|
||||
// This event is used in tests.
|
||||
ed.emit("after-suggest");
|
||||
});
|
||||
popup.hidePopup();
|
||||
return;
|
||||
}
|
||||
// The cursor is at the end of the currently entered part of the token,
|
||||
// like "backgr|" but we need to open the popup at the beginning of the
|
||||
// character "b". Thus we need to calculate the width of the entered part
|
||||
// of the token ("backgr" here). 4 comes from the popup's left padding.
|
||||
|
||||
let cursorElement = cm.display.cursorDiv.querySelector(".CodeMirror-cursor");
|
||||
let left = suggestions[0].preLabel.length * cm.defaultCharWidth() + 4;
|
||||
popup.hidePopup();
|
||||
popup.setItems(suggestions);
|
||||
|
||||
popup.once("popup-opened", () => {
|
||||
// This event is used in tests.
|
||||
ed.emit("after-suggest");
|
||||
}).then(null, e => console.error(e));
|
||||
});
|
||||
popup.openPopup(cursorElement, -1 * left, 0);
|
||||
autocompleteOpts.suggestionInsertedOnce = false;
|
||||
}).then(null, e => console.error(e));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -45,6 +45,16 @@
|
|||
max-height: 20rem;
|
||||
}
|
||||
|
||||
/* Reset list styles. */
|
||||
.devtools-autocomplete-popup ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.devtools-autocomplete-popup ul,
|
||||
.devtools-autocomplete-popup li {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
:root[platform="linux"] .devtools-autocomplete-popup {
|
||||
/* Root font size is bigger on Linux, adjust rem-based values. */
|
||||
max-height: 16rem;
|
||||
|
@ -55,50 +65,50 @@
|
|||
background-color: transparent;
|
||||
border-width: 0px !important;
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox > scrollbox {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.inplace-editor-autocomplete-popup .devtools-autocomplete-listbox {
|
||||
/* Inplace editor closes the autocomplete popup on blur, the autocomplete
|
||||
popup should not steal the focus here.*/
|
||||
-moz-user-focus: ignore;
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox > richlistitem,
|
||||
.devtools-autocomplete-listbox > richlistitem[selected] {
|
||||
.devtools-autocomplete-listbox .autocomplete-item {
|
||||
width: 100%;
|
||||
background-color: transparent;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox.dark-theme > richlistitem[selected],
|
||||
.devtools-autocomplete-listbox.dark-theme > richlistitem:hover {
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox.dark-theme > richlistitem[selected] > .autocomplete-value,
|
||||
.devtools-autocomplete-listbox:focus.dark-theme > richlistitem[selected] > .initial-value {
|
||||
color: hsl(208,100%,60%);
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox.dark-theme > richlistitem[selected] > label {
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox.dark-theme > richlistitem > label {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox > richlistitem > .initial-value,
|
||||
.devtools-autocomplete-listbox > richlistitem > .autocomplete-value {
|
||||
margin: 0;
|
||||
padding: 1px 0;
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox > richlistitem > .autocomplete-count {
|
||||
.devtools-autocomplete-listbox .autocomplete-selected {
|
||||
background-color: rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox.dark-theme .autocomplete-selected,
|
||||
.devtools-autocomplete-listbox.dark-theme .autocomplete-item:hover {
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox.dark-theme .autocomplete-selected > .autocomplete-value,
|
||||
.devtools-autocomplete-listbox:focus.dark-theme .autocomplete-selected > .initial-value {
|
||||
color: hsl(208,100%,60%);
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox.dark-theme .autocomplete-selected > span {
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox.dark-theme .autocomplete-item > span {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox .autocomplete-item > .initial-value,
|
||||
.devtools-autocomplete-listbox .autocomplete-item > .autocomplete-value {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox .autocomplete-item > .autocomplete-count {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
|
@ -132,22 +142,22 @@
|
|||
background: var(--theme-body-background);
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox.firebug-theme > richlistitem[selected],
|
||||
.devtools-autocomplete-listbox.firebug-theme > richlistitem:hover,
|
||||
.devtools-autocomplete-listbox.light-theme > richlistitem[selected],
|
||||
.devtools-autocomplete-listbox.light-theme > richlistitem:hover {
|
||||
.devtools-autocomplete-listbox.firebug-theme .autocomplete-selected,
|
||||
.devtools-autocomplete-listbox.firebug-theme .autocomplete-item:hover,
|
||||
.devtools-autocomplete-listbox.light-theme .autocomplete-selected,
|
||||
.devtools-autocomplete-listbox.light-theme .autocomplete-item:hover {
|
||||
background-color: rgba(128,128,128,0.3);
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox.firebug-theme > richlistitem[selected] > .autocomplete-value,
|
||||
.devtools-autocomplete-listbox:focus.firebug-theme > richlistitem[selected] > .initial-value,
|
||||
.devtools-autocomplete-listbox.light-theme > richlistitem[selected] > .autocomplete-value,
|
||||
.devtools-autocomplete-listbox:focus.light-theme > richlistitem[selected] > .initial-value {
|
||||
.devtools-autocomplete-listbox.firebug-theme .autocomplete-selected > .autocomplete-value,
|
||||
.devtools-autocomplete-listbox:focus.firebug-theme .autocomplete-selected > .initial-value,
|
||||
.devtools-autocomplete-listbox.light-theme .autocomplete-selected > .autocomplete-value,
|
||||
.devtools-autocomplete-listbox:focus.light-theme .autocomplete-selected > .initial-value {
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox.firebug-theme > richlistitem > label,
|
||||
.devtools-autocomplete-listbox.light-theme > richlistitem > label {
|
||||
.devtools-autocomplete-listbox.firebug-theme .autocomplete-item > span,
|
||||
.devtools-autocomplete-listbox.light-theme .autocomplete-item > span {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
/* Tooltip widget (see devtools/client/shared/widgets/Tooltip.js) */
|
||||
|
||||
.devtools-tooltip .panel-arrowcontent {
|
||||
|
@ -107,6 +106,7 @@
|
|||
background: transparent;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
filter: drop-shadow(0 3px 4px var(--theme-tooltip-shadow));
|
||||
}
|
||||
|
||||
.tooltip-xul-wrapper {
|
||||
|
@ -144,11 +144,7 @@
|
|||
|
||||
/* Tooltip : arrow style */
|
||||
|
||||
.tooltip-container[type="arrow"] {
|
||||
filter: drop-shadow(0 3px 4px var(--theme-tooltip-shadow));
|
||||
}
|
||||
|
||||
.tooltip-xul-wrapper .tooltip-container[type="arrow"] {
|
||||
.tooltip-xul-wrapper .tooltip-container {
|
||||
/* When displayed in a XUL panel the drop shadow would be abruptly cut by the panel */
|
||||
filter: none;
|
||||
}
|
||||
|
@ -390,3 +386,25 @@
|
|||
.stack-frame-line {
|
||||
color: var(--theme-highlight-orange);
|
||||
}
|
||||
|
||||
/* Tooltip: HTML Search */
|
||||
|
||||
#searchbox-panel-listbox {
|
||||
width: 250px;
|
||||
max-width: 250px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
#searchbox-panel-listbox .autocomplete-item,
|
||||
#searchbox-panel-listbox .autocomplete-item[selected] {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
#searchbox-panel-listbox .autocomplete-item > .initial-value {
|
||||
max-width: 130px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
#searchbox-panel-listbox .autocomplete-item > .autocomplete-value {
|
||||
max-width: 150px;
|
||||
}
|
||||
|
|
|
@ -246,17 +246,21 @@ JSTerm.prototype = {
|
|||
let autocompleteOptions = {
|
||||
onSelect: this.onAutocompleteSelect.bind(this),
|
||||
onClick: this.acceptProposedCompletion.bind(this),
|
||||
panelId: "webConsole_autocompletePopup",
|
||||
listBoxId: "webConsole_autocompletePopupListBox",
|
||||
position: "before_start",
|
||||
listId: "webConsole_autocompletePopupListBox",
|
||||
position: "top",
|
||||
theme: "auto",
|
||||
direction: "ltr",
|
||||
autoSelect: true
|
||||
};
|
||||
this.autocompletePopup = new AutocompletePopup(this.hud.document,
|
||||
autocompleteOptions);
|
||||
|
||||
let doc = this.hud.document;
|
||||
|
||||
let toolbox = gDevTools.getToolbox(this.hud.owner.target);
|
||||
if (!toolbox) {
|
||||
// In some cases (e.g. Browser Console), there is no toolbox.
|
||||
toolbox = { doc };
|
||||
}
|
||||
this.autocompletePopup = new AutocompletePopup(toolbox, autocompleteOptions);
|
||||
|
||||
let inputContainer = doc.querySelector(".jsterm-input-container");
|
||||
this.completeNode = doc.querySelector(".jsterm-complete-node");
|
||||
this.inputNode = doc.querySelector(".jsterm-input-node");
|
||||
|
@ -1701,12 +1705,6 @@ JSTerm.prototype = {
|
|||
this.autocompletePopup.destroy();
|
||||
this.autocompletePopup = null;
|
||||
|
||||
let popup = this.hud.owner.chromeWindow.document
|
||||
.getElementById("webConsole_autocompletePopup");
|
||||
if (popup) {
|
||||
popup.parentNode.removeChild(popup);
|
||||
}
|
||||
|
||||
if (this._onPaste) {
|
||||
this.inputNode.removeEventListener("paste", this._onPaste, false);
|
||||
this.inputNode.removeEventListener("drop", this._onPaste, false);
|
||||
|
|
|
@ -14,7 +14,7 @@ add_task(function* () {
|
|||
yield loadTab(TEST_URI);
|
||||
let hud = yield openConsole();
|
||||
let popup = hud.jsterm.autocompletePopup;
|
||||
let popupShown = once(popup._panel, "popupshown");
|
||||
let popupShown = once(popup, "popup-opened");
|
||||
|
||||
hud.jsterm.setInputValue("sc");
|
||||
EventUtils.synthesizeKey("r", {});
|
||||
|
|
|
@ -30,9 +30,9 @@ add_task(function* () {
|
|||
Services.prefs.setBoolPref(PREF_AUTO_MULTILINE, true);
|
||||
});
|
||||
|
||||
var consoleOpened = Task.async(function* (aHud) {
|
||||
var consoleOpened = Task.async(function* (hud) {
|
||||
let deferred = promise.defer();
|
||||
HUD = aHud;
|
||||
HUD = hud;
|
||||
info("web console opened");
|
||||
|
||||
jsterm = HUD.jsterm;
|
||||
|
@ -51,9 +51,7 @@ var consoleOpened = Task.async(function* (aHud) {
|
|||
|
||||
ok(!popup.isOpen, "popup is not open");
|
||||
|
||||
popup._panel.addEventListener("popupshown", function onShown() {
|
||||
popup._panel.removeEventListener("popupshown", onShown, false);
|
||||
|
||||
popup.once("popup-opened", () => {
|
||||
ok(popup.isOpen, "popup is open");
|
||||
|
||||
// 4 values, and the following properties:
|
||||
|
@ -65,6 +63,7 @@ var consoleOpened = Task.async(function* (aHud) {
|
|||
let sameItems = popup.getItems().reverse().map(function (e) {
|
||||
return e.label;
|
||||
});
|
||||
|
||||
ok(sameItems.every(function (prop, index) {
|
||||
return [
|
||||
"__defineGetter__",
|
||||
|
@ -134,14 +133,12 @@ var consoleOpened = Task.async(function* (aHud) {
|
|||
is(popup.selectedIndex, 0, "index is first after Home");
|
||||
|
||||
info("press Tab and wait for popup to hide");
|
||||
popup._panel.addEventListener("popuphidden", function popupHidden() {
|
||||
popup._panel.removeEventListener("popuphidden", popupHidden, false);
|
||||
popup.once("popup-closed", () => {
|
||||
deferred.resolve();
|
||||
}, false);
|
||||
});
|
||||
EventUtils.synthesizeKey("VK_TAB", {});
|
||||
}, false);
|
||||
});
|
||||
|
||||
info("wait for completion: window.foobarBug585991.");
|
||||
jsterm.setInputValue("window.foobarBug585991");
|
||||
EventUtils.synthesizeKey(".", {});
|
||||
|
||||
|
@ -159,9 +156,7 @@ function popupHideAfterTab() {
|
|||
|
||||
ok(!completeNode.value, "completeNode is empty");
|
||||
|
||||
popup._panel.addEventListener("popupshown", function onShown() {
|
||||
popup._panel.removeEventListener("popupshown", onShown, false);
|
||||
|
||||
popup.once("popup-opened", function onShown() {
|
||||
ok(popup.isOpen, "popup is open");
|
||||
|
||||
is(popup.itemCount, 19, "popup.itemCount is correct");
|
||||
|
@ -176,9 +171,7 @@ function popupHideAfterTab() {
|
|||
is(completeNode.value, prefix + "watch",
|
||||
"completeNode.value holds watch");
|
||||
|
||||
popup._panel.addEventListener("popuphidden", function onHidden() {
|
||||
popup._panel.removeEventListener("popuphidden", onHidden, false);
|
||||
|
||||
popup.once("popup-closed", function onHidden() {
|
||||
ok(!popup.isOpen, "popup is not open after VK_ESCAPE");
|
||||
|
||||
is(jsterm.getInputValue(), "window.foobarBug585991.",
|
||||
|
@ -207,9 +200,7 @@ function popupHideAfterTab() {
|
|||
function testReturnKey() {
|
||||
let deferred = promise.defer();
|
||||
|
||||
popup._panel.addEventListener("popupshown", function onShown() {
|
||||
popup._panel.removeEventListener("popupshown", onShown, false);
|
||||
|
||||
popup.once("popup-opened", function onShown() {
|
||||
ok(popup.isOpen, "popup is open");
|
||||
|
||||
is(popup.itemCount, 19, "popup.itemCount is correct");
|
||||
|
@ -231,9 +222,7 @@ function testReturnKey() {
|
|||
is(completeNode.value, prefix + "valueOf",
|
||||
"completeNode.value holds valueOf");
|
||||
|
||||
popup._panel.addEventListener("popuphidden", function onHidden() {
|
||||
popup._panel.removeEventListener("popuphidden", onHidden, false);
|
||||
|
||||
popup.once("popup-closed", function onHidden() {
|
||||
ok(!popup.isOpen, "popup is not open after VK_RETURN");
|
||||
|
||||
is(jsterm.getInputValue(), "window.foobarBug585991.valueOf",
|
||||
|
@ -271,9 +260,7 @@ function* dontShowArrayNumbers() {
|
|||
jsterm = HUD.jsterm;
|
||||
popup = jsterm.autocompletePopup;
|
||||
|
||||
popup._panel.addEventListener("popupshown", function onShown() {
|
||||
popup._panel.removeEventListener("popupshown", onShown, false);
|
||||
|
||||
popup.once("popup-opened", function onShown() {
|
||||
let sameItems = popup.getItems().map(function (e) {
|
||||
return e.label;
|
||||
});
|
||||
|
@ -281,8 +268,7 @@ function* dontShowArrayNumbers() {
|
|||
prop === "0";
|
||||
}), "Completing on an array doesn't show numbers.");
|
||||
|
||||
popup._panel.addEventListener("popuphidden", function popupHidden() {
|
||||
popup._panel.removeEventListener("popuphidden", popupHidden, false);
|
||||
popup.once("popup-closed", function popupHidden() {
|
||||
deferred.resolve();
|
||||
}, false);
|
||||
|
||||
|
@ -304,16 +290,13 @@ function testReturnWithNoSelection() {
|
|||
|
||||
info("test pressing return with open popup, but no selection, see bug 873250");
|
||||
|
||||
popup._panel.addEventListener("popupshown", function onShown() {
|
||||
popup._panel.removeEventListener("popupshown", onShown);
|
||||
|
||||
popup.once("popup-opened", function onShown() {
|
||||
ok(popup.isOpen, "popup is open");
|
||||
is(popup.itemCount, 2, "popup.itemCount is correct");
|
||||
isnot(popup.selectedIndex, -1, "popup.selectedIndex is correct");
|
||||
|
||||
info("press Return and wait for popup to hide");
|
||||
popup._panel.addEventListener("popuphidden", function popupHidden() {
|
||||
popup._panel.removeEventListener("popuphidden", popupHidden);
|
||||
popup.once("popup-closed", function popupHidden() {
|
||||
deferred.resolve();
|
||||
});
|
||||
executeSoon(() => EventUtils.synthesizeKey("VK_RETURN", {}));
|
||||
|
@ -344,9 +327,7 @@ function testCompletionInText() {
|
|||
|
||||
let deferred = promise.defer();
|
||||
|
||||
popup._panel.addEventListener("popupshown", function onShown() {
|
||||
popup._panel.removeEventListener("popupshown", onShown);
|
||||
|
||||
popup.once("popup-opened", function onShown() {
|
||||
ok(popup.isOpen, "popup is open");
|
||||
is(popup.itemCount, 2, "popup.itemCount is correct");
|
||||
|
||||
|
@ -360,8 +341,7 @@ function testCompletionInText() {
|
|||
ok(sameItems, "getItems returns the items we expect");
|
||||
|
||||
info("press Tab and wait for popup to hide");
|
||||
popup._panel.addEventListener("popuphidden", function popupHidden() {
|
||||
popup._panel.removeEventListener("popuphidden", popupHidden);
|
||||
popup.once("popup-closed", function popupHidden() {
|
||||
deferred.resolve();
|
||||
});
|
||||
EventUtils.synthesizeKey("VK_TAB", {});
|
||||
|
|
|
@ -26,67 +26,49 @@ function consoleOpened(HUD) {
|
|||
|
||||
let popup = HUD.jsterm.autocompletePopup;
|
||||
|
||||
let input = popup._document.activeElement;
|
||||
function getActiveDescendant() {
|
||||
return input.ownerDocument.getElementById(
|
||||
input.getAttribute("aria-activedescendant"));
|
||||
}
|
||||
|
||||
ok(!popup.isOpen, "popup is not open");
|
||||
ok(!input.hasAttribute("aria-activedescendant"), "no aria-activedescendant");
|
||||
|
||||
popup._panel.addEventListener("popupshown", function onPopupPanel() {
|
||||
popup._panel.removeEventListener("popupshown", onPopupPanel, false);
|
||||
|
||||
popup.once("popup-opened", () => {
|
||||
ok(popup.isOpen, "popup is open");
|
||||
|
||||
is(popup.itemCount, 0, "no items");
|
||||
ok(!input.hasAttribute("aria-activedescendant"),
|
||||
"no aria-activedescendant");
|
||||
|
||||
popup.setItems(items);
|
||||
|
||||
is(popup.itemCount, items.length, "items added");
|
||||
|
||||
let sameItems = popup.getItems();
|
||||
is(sameItems.every(function (aItem, aIndex) {
|
||||
return aItem === items[aIndex];
|
||||
is(sameItems.every(function (item, index) {
|
||||
return item === items[index];
|
||||
}), true, "getItems returns back the same items");
|
||||
|
||||
is(popup.selectedIndex, 2,
|
||||
"Index of the first item from bottom is selected.");
|
||||
is(popup.selectedIndex, 2, "Index of the first item from bottom is selected.");
|
||||
is(popup.selectedItem, items[2], "First item from bottom is selected");
|
||||
ok(getActiveDescendant().selected, "aria-activedescendant is correct");
|
||||
|
||||
popup.selectedIndex = 1;
|
||||
|
||||
is(popup.selectedIndex, 1, "index 1 is selected");
|
||||
is(popup.selectedItem, items[1], "item1 is selected");
|
||||
ok(getActiveDescendant().selected, "aria-activedescendant is correct");
|
||||
|
||||
popup.selectedItem = items[2];
|
||||
|
||||
is(popup.selectedIndex, 2, "index 2 is selected");
|
||||
is(popup.selectedItem, items[2], "item2 is selected");
|
||||
ok(getActiveDescendant().selected, "aria-activedescendant is correct");
|
||||
|
||||
is(popup.selectPreviousItem(), items[1], "selectPreviousItem() works");
|
||||
|
||||
is(popup.selectedIndex, 1, "index 1 is selected");
|
||||
is(popup.selectedItem, items[1], "item1 is selected");
|
||||
ok(getActiveDescendant().selected, "aria-activedescendant is correct");
|
||||
|
||||
is(popup.selectNextItem(), items[2], "selectPreviousItem() works");
|
||||
is(popup.selectNextItem(), items[2], "selectNextItem() works");
|
||||
|
||||
is(popup.selectedIndex, 2, "index 2 is selected");
|
||||
is(popup.selectedItem, items[2], "item2 is selected");
|
||||
ok(getActiveDescendant().selected, "aria-activedescendant is correct");
|
||||
|
||||
ok(popup.selectNextItem(), "selectPreviousItem() works");
|
||||
ok(popup.selectNextItem(), "selectNextItem() works");
|
||||
|
||||
is(popup.selectedIndex, 0, "index 0 is selected");
|
||||
is(popup.selectedItem, items[0], "item0 is selected");
|
||||
ok(getActiveDescendant().selected, "aria-activedescendant is correct");
|
||||
|
||||
items.push({label: "label3", value: "value3"});
|
||||
popup.appendItem(items[3]);
|
||||
|
@ -95,25 +77,23 @@ function consoleOpened(HUD) {
|
|||
|
||||
popup.selectedIndex = 3;
|
||||
is(popup.selectedItem, items[3], "item3 is selected");
|
||||
ok(getActiveDescendant().selected, "aria-activedescendant is correct");
|
||||
|
||||
popup.removeItem(items[2]);
|
||||
|
||||
is(popup.selectedIndex, 2, "index2 is selected");
|
||||
is(popup.selectedItem, items[3], "item3 is still selected");
|
||||
ok(getActiveDescendant().selected, "aria-activedescendant is correct");
|
||||
is(popup.itemCount, items.length - 1, "item2 removed");
|
||||
|
||||
popup.clearItems();
|
||||
is(popup.itemCount, 0, "items cleared");
|
||||
ok(!input.hasAttribute("aria-activedescendant"),
|
||||
"no aria-activedescendant");
|
||||
|
||||
popup.once("popup-closed", () => {
|
||||
deferred.resolve();
|
||||
});
|
||||
popup.hidePopup();
|
||||
deferred.resolve();
|
||||
}, false);
|
||||
});
|
||||
|
||||
popup.openPopup();
|
||||
popup.openPopup(HUD.jsterm.inputNode);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
|
|
@ -33,9 +33,7 @@ function consoleOpened() {
|
|||
|
||||
ok(!popup.isOpen, "popup is not open");
|
||||
|
||||
popup._panel.addEventListener("popupshown", function onShown() {
|
||||
popup._panel.removeEventListener("popupshown", onShown, false);
|
||||
|
||||
popup.once("popup-opened", () => {
|
||||
ok(popup.isOpen, "popup is open");
|
||||
|
||||
is(popup.itemCount, jsterm._autocompleteCache.length,
|
||||
|
@ -47,10 +45,11 @@ function consoleOpened() {
|
|||
isnot(jsterm._autocompleteCache.indexOf("ATTRIBUTE_NODE"), -1,
|
||||
"ATTRIBUTE_NODE is in the list of suggestions");
|
||||
|
||||
popup._panel.addEventListener("popuphidden", deferred.resolve, false);
|
||||
|
||||
popup.once("popup-closed", () => {
|
||||
deferred.resolve();
|
||||
});
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
}, false);
|
||||
});
|
||||
|
||||
jsterm.setInputValue("document.body");
|
||||
EventUtils.synthesizeKey(".", {});
|
||||
|
@ -65,9 +64,6 @@ function autocompletePopupHidden() {
|
|||
let popup = jsterm.autocompletePopup;
|
||||
let completeNode = jsterm.completeNode;
|
||||
|
||||
popup._panel.removeEventListener("popuphidden", autocompletePopupHidden,
|
||||
false);
|
||||
|
||||
ok(!popup.isOpen, "popup is not open");
|
||||
|
||||
jsterm.once("autocomplete-updated", function () {
|
||||
|
@ -89,8 +85,8 @@ function testPropertyPanel() {
|
|||
let jsterm = gHUD.jsterm;
|
||||
jsterm.clearOutput();
|
||||
jsterm.execute("document", (msg) => {
|
||||
jsterm.once("variablesview-fetched", (aEvent, aView) => {
|
||||
deferred.resolve(aView);
|
||||
jsterm.once("variablesview-fetched", (evt, view) => {
|
||||
deferred.resolve(view);
|
||||
});
|
||||
let anchor = msg.querySelector(".message-body a");
|
||||
EventUtils.synthesizeMouse(anchor, 2, 2, {}, gHUD.iframeWindow);
|
||||
|
|
|
@ -25,12 +25,12 @@ function consoleOpened(HUD) {
|
|||
ok(false, "popup shown");
|
||||
};
|
||||
|
||||
jsterm.execute("window.foobarBug660806 = {\
|
||||
'location': 'value0',\
|
||||
'locationbar': 'value1'\
|
||||
}");
|
||||
jsterm.execute(`window.foobarBug660806 = {
|
||||
'location': 'value0',
|
||||
'locationbar': 'value1'
|
||||
}`);
|
||||
|
||||
popup._panel.addEventListener("popupshown", onShown, false);
|
||||
popup.on("popup-opened", onShown);
|
||||
|
||||
ok(!popup.isOpen, "popup is not open");
|
||||
|
||||
|
@ -47,7 +47,7 @@ function consoleOpened(HUD) {
|
|||
|
||||
executeSoon(function () {
|
||||
ok(!popup.isOpen, "popup is not open");
|
||||
popup._panel.removeEventListener("popupshown", onShown, false);
|
||||
popup.off("popup-opened", onShown);
|
||||
executeSoon(deferred.resolve);
|
||||
});
|
||||
return deferred.promise;
|
||||
|
|
|
@ -81,15 +81,14 @@
|
|||
let deferred = promise.defer();
|
||||
let popup = jsterm.autocompletePopup;
|
||||
|
||||
popup._panel.addEventListener("popuphidden", function popupHidden() {
|
||||
popup._panel.removeEventListener("popuphidden", popupHidden, false);
|
||||
popup.once("popup-closed", () => {
|
||||
ok(!popup.isOpen,
|
||||
"Auto complete popup is hidden.");
|
||||
ok(toolbox.splitConsole,
|
||||
"Split console is open after hiding the autocomplete popup.");
|
||||
|
||||
deferred.resolve();
|
||||
}, false);
|
||||
});
|
||||
|
||||
EventUtils.sendKey("ESCAPE", toolbox.win);
|
||||
|
||||
|
@ -136,19 +135,13 @@
|
|||
}
|
||||
|
||||
function showAutoCompletePopoup() {
|
||||
let deferred = promise.defer();
|
||||
let popupPanel = jsterm.autocompletePopup._panel;
|
||||
|
||||
popupPanel.addEventListener("popupshown", function popupShown() {
|
||||
popupPanel.removeEventListener("popupshown", popupShown, false);
|
||||
deferred.resolve();
|
||||
}, false);
|
||||
let onPopupShown = jsterm.autocompletePopup.once("popup-opened");
|
||||
|
||||
jsterm.focus();
|
||||
jsterm.setInputValue("document.location.");
|
||||
EventUtils.sendKey("TAB", hud.iframeWindow);
|
||||
|
||||
return deferred.promise;
|
||||
return onPopupShown;
|
||||
}
|
||||
|
||||
function finish() {
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче