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/. */
"use strict";
const {
Component,
createFactory,
const {
l10n,
const Message = createFactory(
);
loader.lazyRequireGetter(
this,
"GripMessageBody",
);
/**
* This component is responsible for rendering CSS warnings in the Console panel.
*
* CSS warnings are expandable when they have associated CSS selectors so the
* user can inspect any matching DOM elements. Not all CSS warnings have
* associated selectors (those that don't are not expandable) and not all
* selectors match elements in the current page (warnings can appear for styles
* which don't apply to the current page).
*
* @extends Component
*/
class CSSWarning extends Component {
static get propTypes() {
return {
dispatch: PropTypes.func.isRequired,
inWarningGroup: PropTypes.bool.isRequired,
message: PropTypes.object.isRequired,
open: PropTypes.bool,
cssMatchingElements: PropTypes.object,
repeat: PropTypes.any,
serviceContainer: PropTypes.object,
timestampsVisible: PropTypes.bool.isRequired,
setExpanded: PropTypes.func,
};
}
static get defaultProps() {
return {
open: false,
};
}
static get displayName() {
return "CSSWarning";
}
constructor(props) {
super(props);
this.onToggle = this.onToggle.bind(this);
}
onToggle(messageId) {
const { dispatch, message, cssMatchingElements, open } = this.props;
if (open) {
dispatch(actions.messageClose(messageId));
} else if (cssMatchingElements) {
// If the message already has information about the elements matching
// the selectors associated with this CSS warning, just open the message.
dispatch(actions.messageOpen(messageId));
} else {
// Query the server for elements matching the CSS selectors associated
// with this CSS warning and populate the message's additional cssMatchingElements with
// the result. It's an async operation and potentially expensive, so we only do it
// on demand, once, when the component is first expanded.
dispatch(actions.messageGetMatchingElements(message));
dispatch(actions.messageOpen(messageId));
}
}
render() {
const {
dispatch,
message,
open,
cssMatchingElements,
repeat,
serviceContainer,
timestampsVisible,
inWarningGroup,
setExpanded,
} = this.props;
const {
id: messageId,
indent,
cssSelectors,
source,
type,
level,
messageText,
frame,
exceptionDocURL,
timeStamp,
notes,
} = message;
let messageBody;
if (typeof messageText === "string") {
messageBody = messageText;
} else if (
typeof messageText === "object" &&
messageText.type === "longString"
) {
messageBody = `${message.messageText.initial}…`;
}
// Create a message attachment only when the message is open and there is a result
// to the query for elements matching the CSS selectors associated with the message.
const attachment =
open &&
cssMatchingElements !== undefined &&
dom.div(
{ className: "devtools-monospace" },
dom.div(
{ className: "elements-label" },
l10n.getFormatStr("webconsole.cssWarningElements.label", [
cssSelectors,
])
),
GripMessageBody({
dispatch,
escapeWhitespace: false,
grip: cssMatchingElements,
serviceContainer,
setExpanded,
})
);
return Message({
attachment,
collapsible: !!cssSelectors.length,
dispatch,
exceptionDocURL,
frame,
indent,
inWarningGroup,
level,
messageBody,
messageId,
notes,
open,
onToggle: this.onToggle,
repeat,
serviceContainer,
source,
timeStamp,
timestampsVisible,
topLevelClasses: [],
type,
message,
});
}
}
module.exports = createFactory(CSSWarning);