Source code

Revision control

Copy as Markdown

Other Tools

/* 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/. */
var StatusPanel = {
// This is useful for debugging (set to `true` in the interesting state for
// the panel to remain in that state).
_frozen: false,
get panel() {
delete this.panel;
this.panel = document.getElementById("statuspanel");
this.panel.addEventListener(
"transitionend",
this._onTransitionEnd.bind(this)
);
this.panel.addEventListener(
"transitioncancel",
this._onTransitionEnd.bind(this)
);
return this.panel;
},
get isVisible() {
return !this.panel.hasAttribute("inactive");
},
update() {
if (BrowserHandler.kiosk || this._frozen) {
return;
}
let text;
let type;
let types = ["overLink"];
if (XULBrowserWindow.busyUI) {
types.push("status");
}
types.push("defaultStatus");
for (type of types) {
if ((text = XULBrowserWindow[type])) {
break;
}
}
// If it's a long data: URI that uses base64 encoding, truncate to
// a reasonable length rather than trying to display the entire thing.
// We can't shorten arbitrary URIs like this, as bidi etc might mean
// we need the trailing characters for display. But a base64-encoded
// data-URI is plain ASCII, so this is OK for status panel display.
// (See bug 1484071.)
let textCropped = false;
if (text.length > 500 && text.match(/^data:[^,]+;base64,/)) {
text = text.substring(0, 500) + "\u2026";
textCropped = true;
}
if (this._labelElement.value != text || (text && !this.isVisible)) {
this.panel.setAttribute("previoustype", this.panel.getAttribute("type"));
this.panel.setAttribute("type", type);
this._label = text;
this._labelElement.setAttribute(
"crop",
type == "overLink" && !textCropped ? "center" : "end"
);
}
},
get _labelElement() {
delete this._labelElement;
return (this._labelElement = document.getElementById("statuspanel-label"));
},
set _label(val) {
if (!this.isVisible) {
this.panel.removeAttribute("mirror");
this.panel.removeAttribute("sizelimit");
}
if (
this.panel.getAttribute("type") == "status" &&
this.panel.getAttribute("previoustype") == "status"
) {
// Before updating the label, set the panel's current width as its
// min-width to let the panel grow but not shrink and prevent
// unnecessary flicker while loading pages. We only care about the
// panel's width once it has been painted, so we can do this
// without flushing layout.
this.panel.style.minWidth =
window.windowUtils.getBoundsWithoutFlushing(this.panel).width + "px";
} else {
this.panel.style.minWidth = "";
}
if (val) {
this._labelElement.value = val;
if (this.panel.hidden) {
this.panel.hidden = false;
// This ensures that the "inactive" attribute removal triggers a
// transition.
getComputedStyle(this.panel).display;
}
this.panel.removeAttribute("inactive");
MousePosTracker.addListener(this);
} else {
this.panel.setAttribute("inactive", "true");
MousePosTracker.removeListener(this);
}
},
_onTransitionEnd() {
if (!this.isVisible) {
this.panel.hidden = true;
}
},
getMouseTargetRect() {
let container = this.panel.parentNode;
let panelRect = window.windowUtils.getBoundsWithoutFlushing(this.panel);
let containerRect = window.windowUtils.getBoundsWithoutFlushing(container);
return {
top: panelRect.top,
bottom: panelRect.bottom,
left: RTL_UI ? containerRect.right - panelRect.width : containerRect.left,
right: RTL_UI
? containerRect.right
: containerRect.left + panelRect.width,
};
},
onMouseEnter() {
this._mirror();
},
onMouseLeave() {
this._mirror();
},
_mirror() {
if (this._frozen) {
return;
}
if (this.panel.hasAttribute("mirror")) {
this.panel.removeAttribute("mirror");
} else {
this.panel.setAttribute("mirror", "true");
}
if (!this.panel.hasAttribute("sizelimit")) {
this.panel.setAttribute("sizelimit", "true");
}
},
};