зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1654684 - Add sheet-indicator and preview navigation to the print preview. r=mstriemer,fluent-reviewers,flod
Differential Revision: https://phabricator.services.mozilla.com/D96737
This commit is contained in:
Родитель
c5963a5340
Коммит
0c4bb65e4d
|
@ -1422,6 +1422,19 @@ toolbarpaletteitem > toolbaritem {
|
|||
font-size: large;
|
||||
}
|
||||
|
||||
printpreview-pagination {
|
||||
opacity: 0;
|
||||
transition: opacity 100ms 500ms;
|
||||
}
|
||||
printpreview-pagination:focus-within,
|
||||
.previewStack:hover > printpreview-pagination {
|
||||
opacity: 1;
|
||||
transition: opacity 100ms;
|
||||
}
|
||||
.previewStack[rendering=true] > printpreview-pagination {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.previewStack {
|
||||
background-color: #2A2A2E;
|
||||
|
|
|
@ -55,6 +55,10 @@ async function testPrintPreview() {
|
|||
);
|
||||
|
||||
gBrowser.getTabDialogBox(gBrowser.selectedBrowser).abortAllDialogs();
|
||||
// Wait for the preview to go away
|
||||
await BrowserTestUtils.waitForCondition(
|
||||
() => !document.querySelector(".printPreviewBrowser")
|
||||
);
|
||||
|
||||
await extension.awaitFinish("tabs.printPreview");
|
||||
}
|
||||
|
|
|
@ -20,6 +20,12 @@ ChromeUtils.defineModuleGetter(
|
|||
"resource://gre/modules/ReaderMode.jsm"
|
||||
);
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"DeferredTask",
|
||||
"resource://gre/modules/DeferredTask.jsm"
|
||||
);
|
||||
|
||||
let gPrintPreviewInitializingInfo = null;
|
||||
|
||||
let gPendingPreviewsMap = new Map();
|
||||
|
@ -87,6 +93,17 @@ class PrintingChild extends JSWindowActorChild {
|
|||
this.updatePageCount();
|
||||
break;
|
||||
}
|
||||
|
||||
case "scroll":
|
||||
if (!this._scrollTask) {
|
||||
this._scrollTask = new DeferredTask(
|
||||
() => this.updateCurrentPage(),
|
||||
16,
|
||||
16
|
||||
);
|
||||
}
|
||||
this._scrollTask.arm();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -420,6 +437,14 @@ class PrintingChild extends JSWindowActorChild {
|
|||
});
|
||||
}
|
||||
|
||||
updateCurrentPage() {
|
||||
let cv = this.docShell.contentViewer;
|
||||
cv.QueryInterface(Ci.nsIWebBrowserPrint);
|
||||
this.sendAsyncMessage("Printing:Preview:CurrentPage", {
|
||||
currentPage: cv.printPreviewCurrentPageNumber,
|
||||
});
|
||||
}
|
||||
|
||||
navigate(navType, pageNum) {
|
||||
let cv = this.docShell.contentViewer;
|
||||
cv.QueryInterface(Ci.nsIWebBrowserPrint);
|
||||
|
|
|
@ -33,10 +33,15 @@ class PrintingParent extends JSWindowActorParent {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
let listener = PrintUtils._webProgressPP.value;
|
||||
let listener = PrintUtils._webProgressPP?.value;
|
||||
let data = message.data;
|
||||
|
||||
switch (message.name) {
|
||||
case "Printing:Preview:CurrentPage": {
|
||||
browser.setAttribute("current-page", message.data.currentPage);
|
||||
break;
|
||||
}
|
||||
|
||||
case "Printing:Preview:Entered": {
|
||||
// This message is sent by the content process once it has completed
|
||||
// putting the content into print preview mode. We must wait for that to
|
||||
|
|
|
@ -757,6 +757,7 @@ var PrintEventHandler = {
|
|||
detail: { sheetCount, totalPages: totalPageCount },
|
||||
})
|
||||
);
|
||||
this.previewBrowser.setAttribute("sheet-count", sheetCount);
|
||||
|
||||
this._hideRenderingIndicator();
|
||||
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
/* 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/. */
|
||||
|
||||
:host {
|
||||
/* in-content/common.css variables */
|
||||
--blue-50: #0a84ff;
|
||||
--grey-90-a10: rgba(12, 12, 13, 0.1);
|
||||
--shadow-30: 0 4px 16px var(--grey-90-a10);
|
||||
--border-active-shadow: var(--blue-50);
|
||||
--border-active-color: ButtonShadow;
|
||||
}
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: 24px;
|
||||
inset-inline-start: 50%;
|
||||
translate: -50%;
|
||||
}
|
||||
:host(:-moz-locale-dir(rtl)) {
|
||||
translate: 50%;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin-inline: auto;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
box-shadow: var(--shadow-30);
|
||||
color: var(--toolbar-color);
|
||||
background-color: var(--toolbar-bgcolor);
|
||||
border-radius: 6px;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
.toolbarButton,
|
||||
.toolbarCenter {
|
||||
align-self: stretch;
|
||||
flex: 0 0 auto;
|
||||
padding: var(--toolbarbutton-outer-padding);
|
||||
border: none;
|
||||
border-inline-end: 1px solid ThreeDShadow;
|
||||
border-block: 1px solid ThreeDShadow;
|
||||
color: inherit;
|
||||
background-color: transparent;
|
||||
}
|
||||
.startItem {
|
||||
border-inline-start: 1px solid ThreeDShadow;
|
||||
border-start-start-radius: 6px;
|
||||
border-end-start-radius: 6px;
|
||||
}
|
||||
.endItem {
|
||||
border-start-end-radius: 6px;
|
||||
border-end-end-radius: 6px;
|
||||
}
|
||||
|
||||
.toolbarButton {
|
||||
min-width: calc(2 * var(--toolbarbutton-inner-padding) + 16px);
|
||||
min-height: calc(2 * var(--toolbarbutton-inner-padding) + 16px);
|
||||
}
|
||||
|
||||
.toolbarButton::after {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
vertical-align: text-bottom;
|
||||
text-align: center;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-size: 12px;
|
||||
-moz-context-properties: fill, fill-opacity;
|
||||
fill: var(--lwt-toolbarbutton-icon-fill, currentColor);
|
||||
fill-opacity: var(--toolbarbutton-icon-fill-opacity);
|
||||
}
|
||||
|
||||
.toolbarButton:hover {
|
||||
background-color: var(--toolbarbutton-hover-background);
|
||||
}
|
||||
.toolbarButton:hover:active {
|
||||
background-color: var(--toolbarbutton-active-background);
|
||||
}
|
||||
.toolbarButton::-moz-focus-inner {
|
||||
border: none;
|
||||
}
|
||||
.toolbarButton:focus {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.toolbarButton:-moz-focusring {
|
||||
outline: 2px solid var(--border-active-shadow);
|
||||
}
|
||||
.toolbarButton.startItem:-moz-focusring,
|
||||
.toolbarButton.endItem:-moz-locale-dir(rtl):-moz-focusring {
|
||||
-moz-outline-radius: 8px;
|
||||
-moz-outline-radius-topright: 0;
|
||||
-moz-outline-radius-bottomright: 0;
|
||||
}
|
||||
.toolbarButton.endItem:-moz-focusring,
|
||||
.toolbarButton.startItem:-moz-locale-dir(rtl):-moz-focusring {
|
||||
-moz-outline-radius: 8px;
|
||||
-moz-outline-radius-topleft: 0;
|
||||
-moz-outline-radius-bottomleft: 0;
|
||||
}
|
||||
|
||||
.toolbarCenter {
|
||||
flex-shrink: 0;
|
||||
/* 3 chars + (3px border + 1px padding) on both sides */
|
||||
min-width: calc(8px + 3ch);
|
||||
padding: 0 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#navigateHome::after,
|
||||
#navigateEnd::after {
|
||||
background-image: url("chrome://global/skin/icons/chevron.svg");
|
||||
}
|
||||
|
||||
#navigatePrevious::after,
|
||||
#navigateNext::after {
|
||||
background-image: url("chrome://global/skin/icons/arrow-left.svg");
|
||||
}
|
||||
|
||||
#navigatePrevious:-moz-locale-dir(rtl)::after,
|
||||
#navigateEnd:-moz-locale-dir(rtl)::after,
|
||||
#navigateHome:-moz-locale-dir(ltr)::after,
|
||||
#navigateNext:-moz-locale-dir(ltr)::after {
|
||||
transform: scaleX(-1);
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
// This file is loaded into the browser window scope.
|
||||
/* eslint-env mozilla/browser-window */
|
||||
|
||||
// -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*-
|
||||
|
||||
/* 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/. */
|
||||
|
||||
customElements.define(
|
||||
"printpreview-pagination",
|
||||
class PrintPreviewPagination extends HTMLElement {
|
||||
static get markup() {
|
||||
return `
|
||||
<html:link rel="stylesheet" href="chrome://global/content/printPagination.css" />
|
||||
<html:div class="container">
|
||||
<html:button id="navigateHome" class="toolbarButton startItem" data-l10n-id="printpreview-homearrow-button"></html:button>
|
||||
<html:button id="navigatePrevious" class="toolbarButton" data-l10n-id="printpreview-previousarrow-button"></html:button>
|
||||
<html:div class="toolbarCenter"><html:span id="sheetIndicator" data-l10n-id="printpreview-sheet-of-sheets" data-l10n-args='{ "sheetNum": 1, "sheetCount": 1 }'></html:span></html:div>
|
||||
<html:button id="navigateNext" class="toolbarButton" data-l10n-id="printpreview-nextarrow-button"></html:button>
|
||||
<html:button id="navigateEnd" class="toolbarButton endItem" data-l10n-id="printpreview-endarrow-button"></html:button>
|
||||
</html:div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get defaultProperties() {
|
||||
return {
|
||||
currentPage: 1,
|
||||
sheetCount: 1,
|
||||
};
|
||||
}
|
||||
|
||||
get previewBrowser() {
|
||||
// Assuming we're a sibling of our preview browser.
|
||||
return this.parentNode.querySelector(".printPreviewBrowser");
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
MozXULElement.insertFTLIfNeeded("toolkit/printing/printPreview.ftl");
|
||||
|
||||
const shadowRoot = this.attachShadow({ mode: "open" });
|
||||
document.l10n.connectRoot(shadowRoot);
|
||||
|
||||
let fragment = MozXULElement.parseXULToFragment(this.constructor.markup);
|
||||
this.shadowRoot.append(fragment);
|
||||
|
||||
this.elements = {
|
||||
sheetIndicator: shadowRoot.querySelector("#sheetIndicator"),
|
||||
homeButton: shadowRoot.querySelector("#navigateHome"),
|
||||
previousButton: shadowRoot.querySelector("#navigatePrevious"),
|
||||
nextButton: shadowRoot.querySelector("#navigateNext"),
|
||||
endButton: shadowRoot.querySelector("#navigateEnd"),
|
||||
};
|
||||
|
||||
this.shadowRoot.addEventListener("click", this);
|
||||
|
||||
let knownAttrs = {
|
||||
"sheet-count": "sheetCount",
|
||||
"current-page": "currentPage",
|
||||
};
|
||||
this.mutationObserver = new MutationObserver(changes => {
|
||||
let opts = {};
|
||||
for (let change of changes) {
|
||||
let { attributeName, target, type } = change;
|
||||
if (type == "attributes" && attributeName in knownAttrs) {
|
||||
opts[knownAttrs[attributeName]] = parseInt(
|
||||
target.getAttribute(attributeName),
|
||||
10
|
||||
);
|
||||
}
|
||||
}
|
||||
if (opts.sheetCount || opts.currentPage) {
|
||||
this.update(opts);
|
||||
}
|
||||
});
|
||||
this.mutationObserver.observe(this.previewBrowser, {
|
||||
attributes: ["current-page", "sheet-count"],
|
||||
});
|
||||
// Initial render with some default values
|
||||
// We'll be updated with real values when available
|
||||
this.update(this.constructor.defaultProperties);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
document.l10n.disconnectRoot(this.shadowRoot);
|
||||
this.shadowRoot.textContent = "";
|
||||
this.mutationObserver?.disconnect();
|
||||
delete this.mutationObserver;
|
||||
}
|
||||
|
||||
handleEvent(event) {
|
||||
if (event.type == "click" && event.button != 0) {
|
||||
return;
|
||||
}
|
||||
event.stopPropagation();
|
||||
|
||||
switch (event.target) {
|
||||
case this.elements.homeButton:
|
||||
this.navigate(0, 0, "home");
|
||||
break;
|
||||
case this.elements.previousButton:
|
||||
this.navigate(-1, 0, 0);
|
||||
break;
|
||||
case this.elements.nextButton:
|
||||
this.navigate(1, 0, 0);
|
||||
break;
|
||||
case this.elements.endButton:
|
||||
this.navigate(0, 0, "end");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
navigate(aDirection, aPageNum, aHomeOrEnd) {
|
||||
const nsIWebBrowserPrint = Ci.nsIWebBrowserPrint;
|
||||
let targetNum;
|
||||
let navType;
|
||||
// we use only one of aHomeOrEnd, aDirection, or aPageNum
|
||||
if (aHomeOrEnd) {
|
||||
// We're going to either the very first page ("home"), or the
|
||||
// very last page ("end").
|
||||
if (aHomeOrEnd == "home") {
|
||||
targetNum = 1;
|
||||
navType = nsIWebBrowserPrint.PRINTPREVIEW_HOME;
|
||||
} else {
|
||||
targetNum = this.sheetCount;
|
||||
navType = nsIWebBrowserPrint.PRINTPREVIEW_END;
|
||||
}
|
||||
} else if (aPageNum) {
|
||||
// We're going to a specific page (aPageNum)
|
||||
targetNum = Math.min(Math.max(1, aPageNum), this.sheetCount);
|
||||
navType = nsIWebBrowserPrint.PRINTPREVIEW_GOTO_PAGENUM;
|
||||
} else {
|
||||
// aDirection is either +1 or -1, and allows us to increment
|
||||
// or decrement our currently viewed page.
|
||||
targetNum = Math.min(
|
||||
Math.max(1, this.currentSheet + aDirection),
|
||||
this.sheetCount
|
||||
);
|
||||
navType = nsIWebBrowserPrint.PRINTPREVIEW_GOTO_PAGENUM;
|
||||
}
|
||||
|
||||
// Preemptively update our own state, rather than waiting for the message from the child process
|
||||
// This allows subsequent clicks of next/back to advance 1 page per click if possible
|
||||
// and keeps the UI feeling more responsive
|
||||
this.update({ currentPage: targetNum });
|
||||
|
||||
this.previewBrowser.sendMessageToActor(
|
||||
"Printing:Preview:Navigate",
|
||||
{
|
||||
navType,
|
||||
pageNum: targetNum,
|
||||
},
|
||||
"Printing"
|
||||
);
|
||||
}
|
||||
|
||||
update(data = {}) {
|
||||
if (data.sheetCount) {
|
||||
if (this.sheetCount !== data.sheetCount && this.currentSheet !== 1) {
|
||||
// when sheet count changes, scroll position will get reset
|
||||
this.currentSheet = 1;
|
||||
}
|
||||
this.sheetCount = data.sheetCount;
|
||||
}
|
||||
if (data.currentPage) {
|
||||
this.currentSheet = data.currentPage;
|
||||
}
|
||||
document.l10n.setAttributes(
|
||||
this.elements.sheetIndicator,
|
||||
this.elements.sheetIndicator.dataset.l10nId,
|
||||
{
|
||||
sheetNum: this.currentSheet,
|
||||
sheetCount: this.sheetCount,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
|
@ -175,6 +175,13 @@ var PrintUtils = {
|
|||
true
|
||||
).firstElementChild;
|
||||
previewStack.append(browser);
|
||||
|
||||
// show the toolbar after we go into print preview mode so
|
||||
// that we can initialize the toolbar with total num pages
|
||||
let previewPagination = document.createElement("printpreview-pagination");
|
||||
previewPagination.classList.add("printPreviewNavigation");
|
||||
previewStack.append(previewPagination);
|
||||
|
||||
aDialogBrowser.parentElement.prepend(previewStack);
|
||||
return browser;
|
||||
},
|
||||
|
|
|
@ -15,6 +15,7 @@ toolkit.jar:
|
|||
#endif
|
||||
content/global/landscape.svg (content/landscape.svg)
|
||||
content/global/portrait.svg (content/portrait.svg)
|
||||
content/global/printPreviewPagination.js (content/printPreviewPagination.js)
|
||||
content/global/printPreviewToolbar.js (content/printPreviewToolbar.js)
|
||||
content/global/printUtils.js (content/printUtils.js)
|
||||
content/global/print.js (content/print.js)
|
||||
|
@ -22,3 +23,4 @@ toolkit.jar:
|
|||
content/global/print.css (content/print.css)
|
||||
content/global/toggle-group.css (content/toggle-group.css)
|
||||
content/global/simplifyMode.css (content/simplifyMode.css)
|
||||
content/global/printPagination.css (content/printPagination.css)
|
||||
|
|
|
@ -36,6 +36,10 @@ support-files =
|
|||
support-files =
|
||||
file_print.html
|
||||
|
||||
[browser_preview_navigation.js]
|
||||
support-files =
|
||||
longerArticle.html
|
||||
|
||||
[browser_preview_print_simplify_non_article.js]
|
||||
support-files =
|
||||
simplifyNonArticleSample.html
|
||||
|
|
|
@ -86,10 +86,26 @@ add_task(async function testTabOrder() {
|
|||
|
||||
const previewBrowser = document.querySelector(".printPreviewBrowser");
|
||||
ok(previewBrowser, "Got the print preview browser");
|
||||
let focused = BrowserTestUtils.waitForEvent(previewBrowser, "focus");
|
||||
EventUtils.synthesizeKey("KEY_Tab", { shiftKey: true });
|
||||
|
||||
let focused;
|
||||
let navigationShadowRoot = document.querySelector(".printPreviewNavigation")
|
||||
.shadowRoot;
|
||||
for (let buttonId of [
|
||||
"navigateEnd",
|
||||
"navigateNext",
|
||||
"navigatePrevious",
|
||||
"navigateHome",
|
||||
]) {
|
||||
let button = navigationShadowRoot.getElementById(buttonId);
|
||||
focused = BrowserTestUtils.waitForEvent(button, "focus");
|
||||
await EventUtils.synthesizeKey("KEY_Tab", { shiftKey: true });
|
||||
await focused;
|
||||
ok(true, "Print preview focused after shift+tab");
|
||||
}
|
||||
|
||||
focused = BrowserTestUtils.waitForEvent(previewBrowser, "focus");
|
||||
await EventUtils.synthesizeKey("KEY_Tab", { shiftKey: true });
|
||||
await focused;
|
||||
ok(true, "Print preview focused after shift+tab through the paginator");
|
||||
|
||||
focused = BrowserTestUtils.waitForEvent(gNavToolbox, "focus", true);
|
||||
EventUtils.synthesizeKey("KEY_Tab", { shiftKey: true });
|
||||
|
@ -101,6 +117,17 @@ add_task(async function testTabOrder() {
|
|||
await focused;
|
||||
ok(true, "Print preview focused after tab");
|
||||
|
||||
for (let buttonId of [
|
||||
"navigateHome",
|
||||
"navigatePrevious",
|
||||
"navigateNext",
|
||||
"navigateEnd",
|
||||
]) {
|
||||
let button = navigationShadowRoot.getElementById(buttonId);
|
||||
focused = BrowserTestUtils.waitForEvent(button, "focus");
|
||||
await EventUtils.synthesizeKey("KEY_Tab");
|
||||
await focused;
|
||||
}
|
||||
focused = BrowserTestUtils.waitForEvent(printerPicker, "focus");
|
||||
EventUtils.synthesizeKey("KEY_Tab");
|
||||
await focused;
|
||||
|
|
|
@ -0,0 +1,319 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
function compare10nArgs(elem, expectedValues) {
|
||||
let l10nArgs = elem.ownerDocument.l10n.getAttributes(elem).args;
|
||||
for (let [name, value] of Object.entries(expectedValues)) {
|
||||
if (value !== l10nArgs[name]) {
|
||||
info(
|
||||
`compare10nArgs, expected ${name}: ${value}, actual: ${l10nArgs[name]}`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
async function waitForPageStatusUpdate(elem, expected, message) {
|
||||
await TestUtils.waitForCondition(
|
||||
() => compare10nArgs(elem, expected),
|
||||
message
|
||||
);
|
||||
}
|
||||
|
||||
async function waitUntilVisible(elem, visible = true) {
|
||||
await TestUtils.waitForCondition(
|
||||
() =>
|
||||
BrowserTestUtils.is_visible(elem) &&
|
||||
getComputedStyle(elem).opacity == "1",
|
||||
"Waiting for element to be visible and have opacity:1"
|
||||
);
|
||||
}
|
||||
|
||||
async function waitUntilTransparent(elem) {
|
||||
// Note that is_visible considers a fully transparent element "visible"
|
||||
await TestUtils.waitForCondition(
|
||||
() => getComputedStyle(elem).opacity == "0",
|
||||
"Waiting for element to be have opacity:0"
|
||||
);
|
||||
}
|
||||
|
||||
async function mouseMoveAndWait(elem) {
|
||||
let mouseMovePromise = BrowserTestUtils.waitForEvent(elem, "mousemove");
|
||||
EventUtils.synthesizeMouseAtCenter(elem, { type: "mousemove" });
|
||||
await mouseMovePromise;
|
||||
await TestUtils.waitForTick();
|
||||
}
|
||||
|
||||
add_task(async function testToolbarVisibility() {
|
||||
// move the mouse to a known position
|
||||
await mouseMoveAndWait(gURLBar.textbox);
|
||||
|
||||
await PrintHelper.withTestPage(async helper => {
|
||||
await helper.startPrint();
|
||||
|
||||
let paginationElem = document.querySelector(".printPreviewNavigation");
|
||||
let previewStack = document.querySelector(".previewStack");
|
||||
|
||||
// The toolbar has 0 opacity until we hover or focus it
|
||||
is(getComputedStyle(paginationElem).opacity, "0", "Initially transparent");
|
||||
|
||||
let visiblePromise = waitUntilVisible(paginationElem);
|
||||
paginationElem.shadowRoot.querySelector("#navigateEnd").focus();
|
||||
await visiblePromise;
|
||||
is(
|
||||
getComputedStyle(paginationElem).opacity,
|
||||
"1",
|
||||
"Opaque with button focused"
|
||||
);
|
||||
|
||||
await EventUtils.synthesizeKey("KEY_Tab", {});
|
||||
await waitUntilTransparent(paginationElem);
|
||||
is(getComputedStyle(paginationElem).opacity, "0", "Returns to transparent");
|
||||
|
||||
visiblePromise = waitUntilVisible(paginationElem);
|
||||
info("Waiting for mousemove event, and for the toolbar to become opaque");
|
||||
await mouseMoveAndWait(previewStack);
|
||||
await visiblePromise;
|
||||
is(getComputedStyle(paginationElem).opacity, "1", "Opaque toolbar");
|
||||
|
||||
// put the mouse back where it won't interfere with later tests
|
||||
await mouseMoveAndWait(gURLBar.textbox);
|
||||
await helper.closeDialog();
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function testPreviewSheetCount() {
|
||||
await PrintHelper.withTestPage(async helper => {
|
||||
await helper.startPrint();
|
||||
|
||||
let paginationElem = document.querySelector(".printPreviewNavigation");
|
||||
let paginationSheetIndicator = paginationElem.shadowRoot.querySelector(
|
||||
"#sheetIndicator"
|
||||
);
|
||||
|
||||
// We have to wait for the first _updatePrintPreview to get the sheet count
|
||||
await waitForPageStatusUpdate(
|
||||
paginationSheetIndicator,
|
||||
{ sheetNum: 1, sheetCount: 3 },
|
||||
"Paginator indicates the correct number of sheets"
|
||||
);
|
||||
|
||||
// then switch to page range 1-1 and verify page count changes
|
||||
await helper.dispatchSettingsChange({
|
||||
pageRanges: ["1", "1"],
|
||||
});
|
||||
await waitForPageStatusUpdate(
|
||||
paginationSheetIndicator,
|
||||
{ sheetNum: 1, sheetCount: 1 },
|
||||
"Indicates the updated number of sheets"
|
||||
);
|
||||
|
||||
await helper.closeDialog();
|
||||
}, "longerArticle.html");
|
||||
});
|
||||
|
||||
add_task(async function testPreviewScroll() {
|
||||
await PrintHelper.withTestPage(async helper => {
|
||||
await helper.startPrint();
|
||||
|
||||
let paginationElem = document.querySelector(".printPreviewNavigation");
|
||||
let paginationSheetIndicator = paginationElem.shadowRoot.querySelector(
|
||||
"#sheetIndicator"
|
||||
);
|
||||
// Wait for the first _updatePrintPreview before interacting with the preview
|
||||
await waitForPageStatusUpdate(
|
||||
paginationSheetIndicator,
|
||||
{ sheetNum: 1, sheetCount: 3 },
|
||||
"Paginator indicates the correct number of sheets"
|
||||
);
|
||||
let previewBrowser = PrintUtils.getPreviewBrowser();
|
||||
|
||||
// scroll down the document
|
||||
// and verify the indicator is updated correctly
|
||||
await SpecialPowers.spawn(previewBrowser, [], async function() {
|
||||
const { ContentTaskUtils } = ChromeUtils.import(
|
||||
"resource://testing-common/ContentTaskUtils.jsm"
|
||||
);
|
||||
const EventUtils = ContentTaskUtils.getEventUtils(content);
|
||||
content.focus();
|
||||
EventUtils.synthesizeKey("VK_PAGE_DOWN", {}, content);
|
||||
});
|
||||
await waitForPageStatusUpdate(
|
||||
paginationSheetIndicator,
|
||||
{ sheetNum: 2, sheetCount: 3 },
|
||||
"Indicator updates on scroll"
|
||||
);
|
||||
|
||||
// move focus before closing the dialog
|
||||
helper.get("cancel-button").focus();
|
||||
await helper.closeDialog();
|
||||
}, "longerArticle.html");
|
||||
});
|
||||
|
||||
add_task(async function testPreviewNavigationCommands() {
|
||||
await PrintHelper.withTestPage(async helper => {
|
||||
await helper.startPrint();
|
||||
|
||||
let paginationElem = document.querySelector(".printPreviewNavigation");
|
||||
let paginationSheetIndicator = paginationElem.shadowRoot.querySelector(
|
||||
"#sheetIndicator"
|
||||
);
|
||||
// Wait for the first _updatePrintPreview before interacting with the preview
|
||||
await waitForPageStatusUpdate(
|
||||
paginationSheetIndicator,
|
||||
{ sheetNum: 1, sheetCount: 3 },
|
||||
"Paginator indicates the correct number of sheets"
|
||||
);
|
||||
|
||||
// click the navigation buttons
|
||||
// and verify the indicator is updated correctly
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
paginationElem.shadowRoot.querySelector("#navigateNext"),
|
||||
{}
|
||||
);
|
||||
await waitForPageStatusUpdate(
|
||||
paginationSheetIndicator,
|
||||
{ sheetNum: 2, sheetCount: 3 },
|
||||
"Indicator updates on navigation"
|
||||
);
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
paginationElem.shadowRoot.querySelector("#navigatePrevious"),
|
||||
{}
|
||||
);
|
||||
await waitForPageStatusUpdate(
|
||||
paginationSheetIndicator,
|
||||
{ sheetNum: 1, sheetCount: 3 },
|
||||
"Indicator updates on navigation to previous"
|
||||
);
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
paginationElem.shadowRoot.querySelector("#navigateEnd"),
|
||||
{}
|
||||
);
|
||||
await waitForPageStatusUpdate(
|
||||
paginationSheetIndicator,
|
||||
{ sheetNum: 3, sheetCount: 3 },
|
||||
"Indicator updates on navigation to end"
|
||||
);
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
paginationElem.shadowRoot.querySelector("#navigateHome"),
|
||||
{}
|
||||
);
|
||||
await waitForPageStatusUpdate(
|
||||
paginationSheetIndicator,
|
||||
{ sheetNum: 1, sheetCount: 3 },
|
||||
"Indicator updates on navigation to start"
|
||||
);
|
||||
|
||||
// Test rapid clicks on the navigation buttons
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
paginationElem.shadowRoot.querySelector("#navigateNext"),
|
||||
{}
|
||||
);
|
||||
await helper.awaitAnimationFrame();
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
paginationElem.shadowRoot.querySelector("#navigateNext"),
|
||||
{}
|
||||
);
|
||||
await waitForPageStatusUpdate(
|
||||
paginationSheetIndicator,
|
||||
{ sheetNum: 3, sheetCount: 3 },
|
||||
"2 successive 'next' clicks correctly update the sheet indicator"
|
||||
);
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
paginationElem.shadowRoot.querySelector("#navigatePrevious"),
|
||||
{}
|
||||
);
|
||||
await helper.awaitAnimationFrame();
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
paginationElem.shadowRoot.querySelector("#navigatePrevious"),
|
||||
{}
|
||||
);
|
||||
await waitForPageStatusUpdate(
|
||||
paginationSheetIndicator,
|
||||
{ sheetNum: 1, sheetCount: 3 },
|
||||
"2 successive 'previous' clicks correctly update the sheet indicator"
|
||||
);
|
||||
|
||||
// move focus before closing the dialog
|
||||
helper.get("cancel-button").focus();
|
||||
await helper.awaitAnimationFrame();
|
||||
await helper.closeDialog();
|
||||
}, "longerArticle.html");
|
||||
}).skip(); // Bug 1681026
|
||||
|
||||
add_task(async function testMultiplePreviewNavigation() {
|
||||
await PrintHelper.withTestPage(async helper => {
|
||||
await helper.startPrint();
|
||||
const tab1 = gBrowser.selectedTab;
|
||||
let sheetIndicator = document
|
||||
.querySelector(".printPreviewNavigation")
|
||||
.shadowRoot.querySelector("#sheetIndicator");
|
||||
|
||||
await waitForPageStatusUpdate(
|
||||
sheetIndicator,
|
||||
{ sheetNum: 1, sheetCount: 3 },
|
||||
"Indicator has the correct initial sheetCount"
|
||||
);
|
||||
|
||||
const tab2 = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser,
|
||||
PrintHelper.defaultTestPageUrl
|
||||
);
|
||||
let helper2 = new PrintHelper(tab2.linkedBrowser);
|
||||
await helper2.startPrint();
|
||||
|
||||
let [previewBrowser1, previewBrowser2] = document.querySelectorAll(
|
||||
".printPreviewBrowser"
|
||||
);
|
||||
ok(previewBrowser1 && previewBrowser2, "There are 2 preview browsers");
|
||||
|
||||
let [toolbar1, toolbar2] = document.querySelectorAll(
|
||||
".printPreviewNavigation"
|
||||
);
|
||||
ok(toolbar1 && toolbar2, "There are 2 preview navigation toolbars");
|
||||
is(
|
||||
toolbar1.previewBrowser,
|
||||
previewBrowser1,
|
||||
"toolbar1 has the correct previewBrowser"
|
||||
);
|
||||
sheetIndicator = toolbar1.shadowRoot.querySelector("#sheetIndicator");
|
||||
ok(
|
||||
compare10nArgs(sheetIndicator, { sheetNum: 1, sheetCount: 3 }),
|
||||
"First toolbar has the correct content"
|
||||
);
|
||||
|
||||
is(
|
||||
toolbar2.previewBrowser,
|
||||
previewBrowser2,
|
||||
"toolbar2 has the correct previewBrowser"
|
||||
);
|
||||
sheetIndicator = toolbar2.shadowRoot.querySelector("#sheetIndicator");
|
||||
ok(
|
||||
compare10nArgs(sheetIndicator, { sheetNum: 1, sheetCount: 1 }),
|
||||
"2nd toolbar has the correct content"
|
||||
);
|
||||
|
||||
// Switch back to the first tab and ensure the correct preview navigation is updated when clicked
|
||||
await BrowserTestUtils.switchTab(gBrowser, tab1);
|
||||
sheetIndicator = toolbar1.shadowRoot.querySelector("#sheetIndicator");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
toolbar1.shadowRoot.querySelector("#navigateNext"),
|
||||
{}
|
||||
);
|
||||
await waitForPageStatusUpdate(
|
||||
sheetIndicator,
|
||||
{ sheetNum: 2, sheetCount: 3 },
|
||||
"Indicator updates on navigation"
|
||||
);
|
||||
|
||||
gBrowser.removeTab(tab2);
|
||||
}, "longerArticle.html");
|
||||
});
|
|
@ -4,17 +4,19 @@ const { MockFilePicker } = SpecialPowers;
|
|||
let pickerMocked = false;
|
||||
|
||||
class PrintHelper {
|
||||
static async withTestPage(testFn) {
|
||||
static async withTestPage(testFn, pagePathname) {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["print.tab_modal.enabled", true]],
|
||||
});
|
||||
|
||||
let taskReturn = await BrowserTestUtils.withNewTab(
|
||||
this.defaultTestPageUrl,
|
||||
async function(browser) {
|
||||
let pageUrl = pagePathname
|
||||
? this.getTestPageUrl(pagePathname)
|
||||
: this.defaultTestPageUrl;
|
||||
info("withTestPage: " + pageUrl);
|
||||
let taskReturn = await BrowserTestUtils.withNewTab(pageUrl, async function(
|
||||
browser
|
||||
) {
|
||||
await testFn(new PrintHelper(browser));
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
await SpecialPowers.popPrefEnv();
|
||||
|
||||
|
@ -27,12 +29,16 @@ class PrintHelper {
|
|||
return taskReturn;
|
||||
}
|
||||
|
||||
static get defaultTestPageUrl() {
|
||||
static getTestPageUrl(pathName) {
|
||||
const testPath = getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"http://example.com"
|
||||
);
|
||||
return testPath + "simplifyArticleSample.html";
|
||||
return testPath + pathName;
|
||||
}
|
||||
|
||||
static get defaultTestPageUrl() {
|
||||
return this.getTestPageUrl("simplifyArticleSample.html");
|
||||
}
|
||||
|
||||
static createMockPaper(paperProperties = {}) {
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
@media print {
|
||||
#page-2 {
|
||||
page-break-before: always;
|
||||
}
|
||||
#page-3 {
|
||||
page-break-before: always;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="page-1">Page 1</h1>
|
||||
<h1 id="page-2">Page 2</h1>
|
||||
<h1 id="page-3">Page 3</h1>
|
||||
</body>
|
||||
</html>
|
|
@ -848,6 +848,10 @@
|
|||
"printpreview-toolbar",
|
||||
"chrome://global/content/printPreviewToolbar.js",
|
||||
],
|
||||
[
|
||||
"printpreview-pagination",
|
||||
"chrome://global/content/printPreviewPagination.js",
|
||||
],
|
||||
[
|
||||
"autocomplete-input",
|
||||
"chrome://global/content/elements/autocomplete-input.js",
|
||||
|
|
|
@ -39,6 +39,11 @@ printpreview-page =
|
|||
.value = Page:
|
||||
.accesskey = a
|
||||
|
||||
# Variables
|
||||
# $sheetNum (integer) - The current sheet number
|
||||
# $sheetCount (integer) - The total number of sheets to print
|
||||
printpreview-sheet-of-sheets = { $sheetNum } of { $sheetCount }
|
||||
|
||||
## Variables
|
||||
## $percent (integer) - menuitem percent label
|
||||
## $arrow (String) - UTF-8 arrow character for navigation buttons
|
||||
|
@ -58,3 +63,11 @@ printpreview-endarrow =
|
|||
.label = { $arrow }
|
||||
.tooltiptext = Last page
|
||||
|
||||
printpreview-homearrow-button =
|
||||
.title = First page
|
||||
printpreview-previousarrow-button =
|
||||
.title = Previous page
|
||||
printpreview-nextarrow-button =
|
||||
.title = Next page
|
||||
printpreview-endarrow-button =
|
||||
.title = Last page
|
||||
|
|
|
@ -362,6 +362,7 @@ let JSWINDOWACTORS = {
|
|||
events: {
|
||||
PrintingError: { capture: true },
|
||||
printPreviewUpdate: { capture: true },
|
||||
scroll: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
Загрузка…
Ссылка в новой задаче