This way we can remove the methods we used to update the size of the input based on its content. We take this as an opportunity to change the way we compute a single char dimension, which is used to offset the autocomplete popup so it aligns with the keyword being typed. We used to create a span, put a `x` in it, add it to the document, hidden, and then get its width and height. This is now replaced by setting custom properties for width and height, which we assign respectively a value of `1ch` and `1lh`, so we get the numbers we need. Because we're retrieving those value via the input computed style, we need to register the property and set a proper `<length>` syntax so we can get their px values. Differential Revision: https://phabricator.services.mozilla.com/D310274
145 lines
4.0 KiB
JavaScript
145 lines
4.0 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
/* import-globals-from helper_inplace_editor.js */
|
|
|
|
"use strict";
|
|
|
|
loadHelperScript("helper_inplace_editor.js");
|
|
|
|
const MAX_WIDTH = 300;
|
|
const START_TEXT = "Start text";
|
|
const LONG_TEXT =
|
|
"I am a long text and I will not fit in a 300px container. " +
|
|
"I expect the inplace editor to wrap over more than two lines.";
|
|
|
|
// Test the inplace-editor behavior with a maxWidth configuration option
|
|
// defined.
|
|
|
|
add_task(async function () {
|
|
await addTab("data:text/html;charset=utf-8,inplace editor max width tests");
|
|
const { host, doc } = await createHost();
|
|
|
|
info("Testing the maxWidth option in pixels, to precisely check the size");
|
|
await new Promise(resolve => {
|
|
createInplaceEditorAndClick(
|
|
{
|
|
multiline: true,
|
|
maxWidth: MAX_WIDTH,
|
|
start: testMaxWidth,
|
|
done: resolve,
|
|
},
|
|
doc,
|
|
START_TEXT
|
|
);
|
|
});
|
|
|
|
host.destroy();
|
|
gBrowser.removeCurrentTab();
|
|
});
|
|
|
|
const testMaxWidth = async function (editor) {
|
|
is(editor.input.value, START_TEXT, "Span text content should be used");
|
|
Assert.less(
|
|
editor.input.offsetWidth,
|
|
MAX_WIDTH,
|
|
"Input width should be strictly smaller than MAX_WIDTH"
|
|
);
|
|
is(getLines(editor.input), 1, "Input should display 1 line of text");
|
|
|
|
info("Check a text is on several lines if it does not fit MAX_WIDTH");
|
|
for (const key of LONG_TEXT) {
|
|
EventUtils.sendChar(key);
|
|
checkScrollbars(editor.input);
|
|
}
|
|
|
|
is(editor.input.value, LONG_TEXT, "Long text should be the input value");
|
|
is(
|
|
editor.input.offsetWidth,
|
|
MAX_WIDTH,
|
|
"Input width should be the same as MAX_WIDTH"
|
|
);
|
|
is(getLines(editor.input), 3, "Input should display 3 lines of text");
|
|
checkScrollbars(editor.input);
|
|
|
|
info("Delete all characters on line 3.");
|
|
while (getLines(editor.input) === 3 && editor.input.value) {
|
|
EventUtils.sendKey("BACK_SPACE");
|
|
// wait for a tick so the input can be re-rendered
|
|
await waitForTick();
|
|
checkScrollbars(editor.input);
|
|
}
|
|
|
|
is(
|
|
editor.input.offsetWidth,
|
|
MAX_WIDTH,
|
|
"Input width should be the same as MAX_WIDTH"
|
|
);
|
|
is(getLines(editor.input), 2, "Input should display 2 lines of text");
|
|
checkScrollbars(editor.input);
|
|
|
|
info("Delete all characters on line 2.");
|
|
while (getLines(editor.input) === 2 && editor.input.value) {
|
|
EventUtils.sendKey("BACK_SPACE");
|
|
// wait for a tick so the input can be re-rendered
|
|
await waitForTick();
|
|
checkScrollbars(editor.input);
|
|
}
|
|
|
|
is(getLines(editor.input), 1, "Input should display 1 line of text");
|
|
checkScrollbars(editor.input);
|
|
|
|
info("Delete all characters.");
|
|
while (editor.input.value) {
|
|
EventUtils.sendKey("BACK_SPACE");
|
|
// wait for a tick so the input can be re-rendered
|
|
await waitForTick();
|
|
checkScrollbars(editor.input);
|
|
}
|
|
|
|
Assert.less(
|
|
editor.input.offsetWidth,
|
|
MAX_WIDTH,
|
|
"Input width should again be strictly smaller than MAX_WIDTH"
|
|
);
|
|
Assert.greater(
|
|
editor.input.offsetWidth,
|
|
0,
|
|
"Even with no content, the input has a non-zero width"
|
|
);
|
|
is(getLines(editor.input), 1, "Input should display 1 line of text");
|
|
checkScrollbars(editor.input);
|
|
|
|
info("Leave the inplace-editor");
|
|
EventUtils.sendKey("RETURN");
|
|
};
|
|
|
|
/**
|
|
* Retrieve the current number of lines displayed in the provided textarea.
|
|
*
|
|
* @param {DOMNode} textarea
|
|
* @return {number} the number of lines
|
|
*/
|
|
function getLines(textarea) {
|
|
const win = textarea.ownerDocument.defaultView;
|
|
const style = win.getComputedStyle(textarea);
|
|
return Math.floor(textarea.clientHeight / parseFloat(style.fontSize));
|
|
}
|
|
|
|
/**
|
|
* Verify that the provided textarea has no vertical or horizontal scrollbar.
|
|
*
|
|
* @param {DOMNode} textarea
|
|
*/
|
|
function checkScrollbars(textarea) {
|
|
is(
|
|
textarea.scrollHeight,
|
|
textarea.clientHeight,
|
|
"Textarea should never have vertical scrollbars"
|
|
);
|
|
is(
|
|
textarea.scrollWidth,
|
|
textarea.clientWidth,
|
|
"Textarea should never have horizontal scrollbars"
|
|
);
|
|
}
|