Bug 1157236 - In-content dialogs: Port bug 1043612, bug 1148923 and bug 1141031 to TB. r=mkmelin

This commit is contained in:
Richard Marti 2015-04-21 21:56:28 +02:00
Родитель 03ab024449
Коммит 0477f5cf9e
2 изменённых файлов: 84 добавлений и 12 удалений

Просмотреть файл

@ -19,6 +19,7 @@ let gSubDialog = {
// Store the original instantApply pref for restoring after closing the dialog
_instantApplyOrig: Services.prefs.getBoolPref("browser.preferences.instantApply"),
_resizeObserver: null,
init: function() {
this._frame = document.getElementById("dialogFrame");
@ -180,44 +181,100 @@ let gSubDialog = {
parseFloat(getComputedStyle(groupBoxTitle).borderBottomWidth);
let groupBoxBody = document.getAnonymousElementByAttribute(this._box, "class", "groupbox-body");
// These are deduced from styles which we don't change, so it's safe to get them now:
let boxVerticalPadding = 2 * parseFloat(getComputedStyle(groupBoxBody).paddingTop);
let boxHorizontalPadding = 2 * parseFloat(getComputedStyle(groupBoxBody).paddingLeft);
let frameWidth = docEl.style.width || docEl.scrollWidth + "px";
let frameHeight = docEl.style.height || docEl.scrollHeight + "px";
let boxVerticalBorder = 2 * parseFloat(getComputedStyle(this._box).borderTopWidth);
let boxHorizontalBorder = 2 * parseFloat(getComputedStyle(this._box).borderLeftWidth);
let boxVerticalBorder = 2 * parseFloat(getComputedStyle(this._box).borderTopWidth);
let frameRect = this._frame.getBoundingClientRect();
// The difference between the frame and box shouldn't change, either:
let boxRect = this._box.getBoundingClientRect();
let frameRect = this._frame.getBoundingClientRect();
let frameSizeDifference = (frameRect.top - boxRect.top) + (boxRect.bottom - frameRect.bottom);
// Then determine and set a bunch of width stuff:
let frameMinWidth = docEl.style.width || docEl.scrollWidth + "px";
let frameWidth = docEl.getAttribute("width") ? docEl.getAttribute("width") + "px" :
frameMinWidth;
this._frame.style.width = frameWidth;
this._box.style.minWidth = "calc(" +
(boxHorizontalBorder + boxHorizontalPadding) +
"px + " + frameMinWidth + ")";
// Now do the same but for the height. We need to do this afterwards because otherwise
// XUL assumes we'll optimize for height and gives us "wrong" values which then are no
// longer correct after we set the width:
let frameMinHeight = docEl.style.height || docEl.scrollHeight + "px";
let frameHeight = docEl.getAttribute("height") ? docEl.getAttribute("height") + "px" :
frameMinHeight;
// Now check if the frame height we calculated is possible at this window size,
// accounting for titlebar, padding/border and some spacing.
let maxHeight = window.innerHeight - frameSizeDifference - 30;
if (frameHeight > maxHeight) {
// If not, we should probably let the dialog scroll:
frameHeight = maxHeight;
// Do this with a frame height in pixels...
let comparisonFrameHeight;
if (frameHeight.endsWith("em")) {
let fontSize = parseFloat(getComputedStyle(this._frame).fontSize);
comparisonFrameHeight = parseFloat(frameHeight, 10) * fontSize;
} else if (frameHeight.endsWith("px")) {
comparisonFrameHeight = parseFloat(frameHeight, 10);
} else {
Cu.reportError("This dialog (" + this._frame.contentWindow.location.href + ") " +
"set a height in non-px-non-em units ('" + frameHeight + "'), " +
"which is likely to lead to bad sizing in in-content preferences. " +
"Please consider changing this.");
comparisonFrameHeight = parseFloat(frameHeight);
}
if (comparisonFrameHeight > maxHeight) {
// If the height is bigger than that of the window, we should let the contents scroll:
frameHeight = maxHeight + "px";
frameMinHeight = maxHeight + "px";
let containers = this._frame.contentDocument.querySelectorAll('.largeDialogContainer');
for (let container of containers) {
container.classList.add("doScroll");
}
}
this._frame.style.width = frameWidth;
this._frame.style.height = frameHeight;
this._box.style.minHeight = "calc(" +
(boxVerticalBorder + groupBoxTitleHeight + boxVerticalPadding) +
"px + " + frameHeight + ")";
this._box.style.minWidth = "calc(" +
(boxHorizontalBorder + boxHorizontalPadding) +
"px + " + frameWidth + ")";
"px + " + frameMinHeight + ")";
this._overlay.style.visibility = "visible";
this._overlay.style.opacity = ""; // XXX: focus hack continued from _onContentLoaded
this._resizeObserver = new MutationObserver(this._onResize);
this._resizeObserver.observe(this._box, {attributes: true});
this._trapFocus();
},
_onResize: function(mutations) {
let frame = gSubDialog._frame;
// The width and height styles are needed for the initial
// layout of the frame, but afterward they need to be removed
// or their presence will restrict the contents of the <browser>
// from resizing to a smaller size.
frame.style.removeProperty("width");
frame.style.removeProperty("height");
let docEl = frame.contentDocument.documentElement;
let persistedAttributes = docEl.getAttribute("persist");
if (!persistedAttributes.contains("width") &&
!persistedAttributes.contains("height")) {
return;
}
for (let mutation of mutations) {
if (mutation.attributeName == "width") {
docEl.setAttribute("width", docEl.scrollWidth);
} else if (mutation.attributeName == "height") {
docEl.setAttribute("height", docEl.scrollHeight);
}
}
},
_onDialogClosing: function(aEvent) {
this._frame.contentWindow.removeEventListener("dialogclosing", this);
this._closingEvent = aEvent;
@ -302,6 +359,10 @@ let gSubDialog = {
this._frame.removeEventListener("load", this);
this._frame.contentWindow.removeEventListener("dialogclosing", this);
window.removeEventListener("keydown", this, true);
if (this._resizeObserver) {
this._resizeObserver.disconnect();
this._resizeObserver = null;
}
this._untrapFocus();
},

Просмотреть файл

@ -228,6 +228,17 @@ tabs {
-moz-margin-end: 4px !important;
}
/**
* Font dialog menulist fixes
*/
#defaultFontType,
#serif,
#sans-serif,
#monospace {
min-width: 30ch;
}
/**
* Dialog
*/