mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 800857 - Implement debugger frontend for breaking on dom events, r=rcampbell
This commit is contained in:
parent
934e18ae62
commit
98c03e2f04
@ -11,6 +11,7 @@ const DBG_STRINGS_URI = "chrome://browser/locale/devtools/debugger.properties";
|
||||
const NEW_SOURCE_IGNORED_URLS = ["debugger eval code", "self-hosted", "XStringBundle"];
|
||||
const NEW_SOURCE_DISPLAY_DELAY = 200; // ms
|
||||
const FETCH_SOURCE_RESPONSE_DELAY = 200; // ms
|
||||
const FETCH_EVENT_LISTENERS_DELAY = 200; // ms
|
||||
const FRAME_STEP_CLEAR_DELAY = 100; // ms
|
||||
const CALL_STACK_PAGE_SIZE = 25; // frames
|
||||
|
||||
@ -47,6 +48,10 @@ const EVENTS = {
|
||||
CONDITIONAL_BREAKPOINT_POPUP_SHOWING: "Debugger:ConditionalBreakpointPopupShowing",
|
||||
CONDITIONAL_BREAKPOINT_POPUP_HIDING: "Debugger:ConditionalBreakpointPopupHiding",
|
||||
|
||||
// When event listeners are fetched or event breakpoints are updated.
|
||||
EVENT_LISTENERS_FETCHED: "Debugger:EventListenersFetched",
|
||||
EVENT_BREAKPOINTS_UPDATED: "Debugger:EventBreakpointsUpdated",
|
||||
|
||||
// When a file search was performed.
|
||||
FILE_SEARCH_MATCH_FOUND: "Debugger:FileSearch:MatchFound",
|
||||
FILE_SEARCH_MATCH_NOT_FOUND: "Debugger:FileSearch:MatchNotFound",
|
||||
@ -274,9 +279,13 @@ let DebuggerController = {
|
||||
// Reset UI.
|
||||
DebuggerView._handleTabNavigation();
|
||||
|
||||
// Discard all the old sources.
|
||||
// Discard all the cached sources.
|
||||
DebuggerController.Parser.clearCache();
|
||||
SourceUtils.clearCache();
|
||||
|
||||
// Prevent performing any actions that were scheduled before navigation.
|
||||
clearNamedTimeout("event-breakpoints-update");
|
||||
clearNamedTimeout("event-listeners-fetch");
|
||||
break;
|
||||
}
|
||||
case "navigate": {
|
||||
@ -387,7 +396,7 @@ let DebuggerController = {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset UI, discard all the old sources and get them again.
|
||||
// Reset the view and fetch all the sources again.
|
||||
DebuggerView._handleTabNavigation();
|
||||
this.SourceScripts._handleTabNavigation();
|
||||
|
||||
@ -1069,6 +1078,11 @@ SourceScripts.prototype = {
|
||||
DebuggerController.Breakpoints.updateEditorBreakpoints();
|
||||
DebuggerController.Breakpoints.updatePaneBreakpoints();
|
||||
|
||||
// Make sure the events listeners are up to date.
|
||||
if (DebuggerView.instrumentsPaneTab == "events-tab") {
|
||||
DebuggerController.Breakpoints.DOM.scheduleEventListenersFetch();
|
||||
}
|
||||
|
||||
// Signal that a new source has been added.
|
||||
window.emit(EVENTS.NEW_SOURCE);
|
||||
},
|
||||
@ -1110,6 +1124,11 @@ SourceScripts.prototype = {
|
||||
DebuggerController.Breakpoints.updateEditorBreakpoints();
|
||||
DebuggerController.Breakpoints.updatePaneBreakpoints();
|
||||
|
||||
// Make sure the events listeners are up to date.
|
||||
if (DebuggerView.instrumentsPaneTab == "events-tab") {
|
||||
DebuggerController.Breakpoints.DOM.scheduleEventListenersFetch();
|
||||
}
|
||||
|
||||
// Signal that sources have been added.
|
||||
window.emit(EVENTS.SOURCES_ADDED);
|
||||
},
|
||||
@ -1302,6 +1321,82 @@ SourceScripts.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles breaking on event listeners in the currently debugged target.
|
||||
*/
|
||||
function EventListeners() {
|
||||
this._onEventListeners = this._onEventListeners.bind(this);
|
||||
}
|
||||
|
||||
EventListeners.prototype = {
|
||||
/**
|
||||
* A list of event names on which the debuggee will automatically pause
|
||||
* when invoked.
|
||||
*/
|
||||
activeEventNames: [],
|
||||
|
||||
/**
|
||||
* Updates the list of events types with listeners that, when invoked,
|
||||
* will automatically pause the debuggee. The respective events are
|
||||
* retrieved from the UI.
|
||||
*/
|
||||
scheduleEventBreakpointsUpdate: function() {
|
||||
// Make sure we're not sending a batch of closely repeated requests.
|
||||
// This can easily happen when toggling all events of a certain type.
|
||||
setNamedTimeout("event-breakpoints-update", 0, () => {
|
||||
this.activeEventNames = DebuggerView.EventListeners.getCheckedEvents();
|
||||
gThreadClient.pauseOnDOMEvents(this.activeEventNames);
|
||||
|
||||
// Notify that event breakpoints were added/removed on the server.
|
||||
window.emit(EVENTS.EVENT_BREAKPOINTS_UPDATED);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetches the currently attached event listeners from the debugee.
|
||||
*/
|
||||
scheduleEventListenersFetch: function() {
|
||||
let getListeners = aCallback => gThreadClient.eventListeners(aResponse => {
|
||||
this._onEventListeners(aResponse);
|
||||
|
||||
// Notify that event listeners were fetched and shown in the view,
|
||||
// and callback to resume the active thread if necessary.
|
||||
window.emit(EVENTS.EVENT_LISTENERS_FETCHED);
|
||||
aCallback && aCallback();
|
||||
});
|
||||
|
||||
// Make sure we're not sending a batch of closely repeated requests.
|
||||
// This can easily happen whenever new sources are fetched.
|
||||
setNamedTimeout("event-listeners-fetch", FETCH_EVENT_LISTENERS_DELAY, () => {
|
||||
if (gThreadClient.state != "paused") {
|
||||
gThreadClient.interrupt(() => getListeners(() => gThreadClient.resume()));
|
||||
} else {
|
||||
getListeners();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback for the debugger's active thread eventListeners() method.
|
||||
*/
|
||||
_onEventListeners: function(aResponse) {
|
||||
if (aResponse.error) {
|
||||
let msg = "Error getting event listeners: " + aResponse.message;
|
||||
Cu.reportError(msg);
|
||||
dumpn(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add all the listeners in the debugger view event linsteners container.
|
||||
for (let listener of aResponse.listeners) {
|
||||
DebuggerView.EventListeners.addListener(listener, { staged: true });
|
||||
}
|
||||
|
||||
// Flushes all the prepared events into the event listeners container.
|
||||
DebuggerView.EventListeners.commit();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles all the breakpoints in the current debugger.
|
||||
*/
|
||||
@ -1314,8 +1409,6 @@ function Breakpoints() {
|
||||
}
|
||||
|
||||
Breakpoints.prototype = {
|
||||
get activeThread() DebuggerController.activeThread,
|
||||
|
||||
/**
|
||||
* A map of breakpoint promises as tracked by the debugger frontend.
|
||||
* The keys consist of a string representation of the breakpoint location.
|
||||
@ -1492,7 +1585,7 @@ Breakpoints.prototype = {
|
||||
this._added.set(identifier, deferred.promise);
|
||||
|
||||
// Try adding the breakpoint.
|
||||
this.activeThread.setBreakpoint(aLocation, (aResponse, aBreakpointClient) => {
|
||||
gThreadClient.setBreakpoint(aLocation, (aResponse, aBreakpointClient) => {
|
||||
// If the breakpoint response has an "actualLocation" attached, then
|
||||
// the original requested placement for the breakpoint wasn't accepted.
|
||||
if (aResponse.actualLocation) {
|
||||
@ -1787,6 +1880,7 @@ DebuggerController.ThreadState = new ThreadState();
|
||||
DebuggerController.StackFrames = new StackFrames();
|
||||
DebuggerController.SourceScripts = new SourceScripts();
|
||||
DebuggerController.Breakpoints = new Breakpoints();
|
||||
DebuggerController.Breakpoints.DOM = new EventListeners();
|
||||
|
||||
/**
|
||||
* Export some properties to the global scope for easier access.
|
||||
|
@ -38,7 +38,7 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
dumpn("Initializing the SourcesView");
|
||||
|
||||
this.widget = new SideMenuWidget(document.getElementById("sources"), {
|
||||
showCheckboxes: true,
|
||||
showItemCheckboxes: true,
|
||||
showArrows: true
|
||||
});
|
||||
|
||||
@ -932,10 +932,10 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
// Breakpoints can only be set while the debuggee is paused. To avoid
|
||||
// an avalanche of pause/resume interrupts of the main thread, simply
|
||||
// pause it beforehand if it's not already.
|
||||
if (gThreadClient.state == "paused") {
|
||||
enableOthers();
|
||||
} else {
|
||||
if (gThreadClient.state != "paused") {
|
||||
gThreadClient.interrupt(() => enableOthers(() => gThreadClient.resume()));
|
||||
} else {
|
||||
enableOthers();
|
||||
}
|
||||
},
|
||||
|
||||
@ -1495,6 +1495,265 @@ WatchExpressionsView.prototype = Heritage.extend(WidgetMethods, {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Functions handling the event listeners UI.
|
||||
*/
|
||||
function EventListenersView() {
|
||||
dumpn("EventListenersView was instantiated");
|
||||
|
||||
this._onCheck = this._onCheck.bind(this);
|
||||
this._onClick = this._onClick.bind(this);
|
||||
}
|
||||
|
||||
EventListenersView.prototype = Heritage.extend(WidgetMethods, {
|
||||
/**
|
||||
* Initialization function, called when the debugger is started.
|
||||
*/
|
||||
initialize: function() {
|
||||
dumpn("Initializing the EventListenersView");
|
||||
|
||||
this.widget = new SideMenuWidget(document.getElementById("event-listeners"), {
|
||||
theme: "light",
|
||||
showItemCheckboxes: true,
|
||||
showGroupCheckboxes: true
|
||||
});
|
||||
|
||||
this.emptyText = L10N.getStr("noEventListenersText");
|
||||
this._eventCheckboxTooltip = L10N.getStr("eventCheckboxTooltip");
|
||||
this._onSelectorString = " " + L10N.getStr("eventOnSelector") + " ";
|
||||
this._inSourceString = " " + L10N.getStr("eventInSource") + " ";
|
||||
|
||||
this.widget.addEventListener("check", this._onCheck, false);
|
||||
this.widget.addEventListener("click", this._onClick, false);
|
||||
|
||||
// Show an empty label by default.
|
||||
this.empty();
|
||||
},
|
||||
|
||||
/**
|
||||
* Destruction function, called when the debugger is closed.
|
||||
*/
|
||||
destroy: function() {
|
||||
dumpn("Destroying the EventListenersView");
|
||||
|
||||
this.widget.removeEventListener("check", this._onCheck, false);
|
||||
this.widget.removeEventListener("click", this._onClick, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds an event to this event listeners container.
|
||||
*
|
||||
* @param object aListener
|
||||
* The listener object coming from the active thread.
|
||||
* @param object aOptions [optional]
|
||||
* Additional options for adding the source. Supported options:
|
||||
* - staged: true to stage the item to be appended later
|
||||
*/
|
||||
addListener: function(aListener, aOptions = {}) {
|
||||
let { node: { selector }, function: { url }, type } = aListener;
|
||||
|
||||
// If an event item for this listener's url and type was already added,
|
||||
// avoid polluting the view and simply increase the "targets" count.
|
||||
let eventItem = this.getItemForPredicate(aItem =>
|
||||
aItem.attachment.url == url &&
|
||||
aItem.attachment.type == type);
|
||||
if (eventItem) {
|
||||
let { selectors, view: { targets } } = eventItem.attachment;
|
||||
if (selectors.indexOf(selector) == -1) {
|
||||
selectors.push(selector);
|
||||
targets.setAttribute("value", L10N.getFormatStr("eventNodes", selectors.length));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// There's no easy way of grouping event types into higher-level groups,
|
||||
// so we need to do this by hand.
|
||||
let is = (...args) => args.indexOf(type) != -1;
|
||||
let has = str => type.contains(str);
|
||||
let starts = str => type.startsWith(str);
|
||||
let group;
|
||||
|
||||
if (starts("animation")) {
|
||||
group = L10N.getStr("animationEvents");
|
||||
} else if (starts("audio")) {
|
||||
group = L10N.getStr("audioEvents");
|
||||
} else if (is("levelchange")) {
|
||||
group = L10N.getStr("batteryEvents");
|
||||
} else if (is("cut", "copy", "paste")) {
|
||||
group = L10N.getStr("clipboardEvents");
|
||||
} else if (starts("composition")) {
|
||||
group = L10N.getStr("compositionEvents");
|
||||
} else if (starts("device")) {
|
||||
group = L10N.getStr("deviceEvents");
|
||||
} else if (is("fullscreenchange", "fullscreenerror", "orientationchange",
|
||||
"overflow", "resize", "scroll", "underflow", "zoom")) {
|
||||
group = L10N.getStr("displayEvents");
|
||||
} else if (starts("drag") || starts("drop")) {
|
||||
group = L10N.getStr("Drag and dropEvents");
|
||||
} else if (starts("gamepad")) {
|
||||
group = L10N.getStr("gamepadEvents");
|
||||
} else if (is("canplay", "canplaythrough", "durationchange", "emptied",
|
||||
"ended", "loadeddata", "loadedmetadata", "pause", "play", "playing",
|
||||
"ratechange", "seeked", "seeking", "stalled", "suspend", "timeupdate",
|
||||
"volumechange", "waiting")) {
|
||||
group = L10N.getStr("mediaEvents");
|
||||
} else if (is("blocked", "complete", "success", "upgradeneeded", "versionchange")) {
|
||||
group = L10N.getStr("indexedDBEvents");
|
||||
} else if (is("blur", "change", "focus", "focusin", "focusout", "invalid",
|
||||
"reset", "select", "submit")) {
|
||||
group = L10N.getStr("interactionEvents");
|
||||
} else if (starts("key") || is("input")) {
|
||||
group = L10N.getStr("keyboardEvents");
|
||||
} else if (starts("mouse") || has("click") || is("contextmenu", "show", "wheel")) {
|
||||
group = L10N.getStr("mouseEvents");
|
||||
} else if (starts("DOM")) {
|
||||
group = L10N.getStr("mutationEvents");
|
||||
} else if (is("abort", "error", "hashchange", "load", "loadend", "loadstart",
|
||||
"pagehide", "pageshow", "progress", "timeout", "unload", "uploadprogress",
|
||||
"visibilitychange")) {
|
||||
group = L10N.getStr("navigationEvents");
|
||||
} else if (is("pointerlockchange", "pointerlockerror")) {
|
||||
group = L10N.getStr("Pointer lockEvents");
|
||||
} else if (is("compassneedscalibration", "userproximity")) {
|
||||
group = L10N.getStr("sensorEvents");
|
||||
} else if (starts("storage")) {
|
||||
group = L10N.getStr("storageEvents");
|
||||
} else if (is("beginEvent", "endEvent", "repeatEvent")) {
|
||||
group = L10N.getStr("timeEvents");
|
||||
} else if (starts("touch")) {
|
||||
group = L10N.getStr("touchEvents");
|
||||
} else {
|
||||
group = L10N.getStr("otherEvents");
|
||||
}
|
||||
|
||||
// Create the element node for the event listener item.
|
||||
let itemView = this._createItemView(type, selector, url);
|
||||
|
||||
// Event breakpoints survive target navigations. Make sure the newly
|
||||
// inserted event item is correctly checked.
|
||||
let checkboxState =
|
||||
DebuggerController.Breakpoints.DOM.activeEventNames.indexOf(type) != -1;
|
||||
|
||||
// Append an event listener item to this container.
|
||||
this.push([itemView.container, url, group], {
|
||||
staged: aOptions.staged, /* stage the item to be appended later? */
|
||||
attachment: {
|
||||
url: url,
|
||||
type: type,
|
||||
view: itemView,
|
||||
selectors: [selector],
|
||||
checkboxState: checkboxState,
|
||||
checkboxTooltip: this._eventCheckboxTooltip
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets all the event types known to this container.
|
||||
*
|
||||
* @return array
|
||||
* List of event types, for example ["load", "click"...]
|
||||
*/
|
||||
getAllEvents: function() {
|
||||
return this.attachments.map(e => e.type);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the checked event types in this container.
|
||||
*
|
||||
* @return array
|
||||
* List of event types, for example ["load", "click"...]
|
||||
*/
|
||||
getCheckedEvents: function() {
|
||||
return this.attachments.filter(e => e.checkboxState).map(e => e.type);
|
||||
},
|
||||
|
||||
/**
|
||||
* Customization function for creating an item's UI.
|
||||
*
|
||||
* @param string aType
|
||||
* The event type, for example "click".
|
||||
* @param string aSelector
|
||||
* The target element's selector.
|
||||
* @param string url
|
||||
* The source url in which the event listener is located.
|
||||
* @return object
|
||||
* An object containing the event listener view nodes.
|
||||
*/
|
||||
_createItemView: function(aType, aSelector, aUrl) {
|
||||
let container = document.createElement("hbox");
|
||||
container.className = "dbg-event-listener";
|
||||
|
||||
let eventType = document.createElement("label");
|
||||
eventType.className = "plain dbg-event-listener-type";
|
||||
eventType.setAttribute("value", aType);
|
||||
container.appendChild(eventType);
|
||||
|
||||
let typeSeparator = document.createElement("label");
|
||||
typeSeparator.className = "plain dbg-event-listener-separator";
|
||||
typeSeparator.setAttribute("value", this._onSelectorString);
|
||||
container.appendChild(typeSeparator);
|
||||
|
||||
let eventTargets = document.createElement("label");
|
||||
eventTargets.className = "plain dbg-event-listener-targets";
|
||||
eventTargets.setAttribute("value", aSelector);
|
||||
container.appendChild(eventTargets);
|
||||
|
||||
let selectorSeparator = document.createElement("label");
|
||||
selectorSeparator.className = "plain dbg-event-listener-separator";
|
||||
selectorSeparator.setAttribute("value", this._inSourceString);
|
||||
container.appendChild(selectorSeparator);
|
||||
|
||||
let eventLocation = document.createElement("label");
|
||||
eventLocation.className = "plain dbg-event-listener-location";
|
||||
eventLocation.setAttribute("value", SourceUtils.getSourceLabel(aUrl));
|
||||
eventLocation.setAttribute("flex", "1");
|
||||
eventLocation.setAttribute("crop", "center");
|
||||
container.appendChild(eventLocation);
|
||||
|
||||
return {
|
||||
container: container,
|
||||
type: eventType,
|
||||
targets: eventTargets,
|
||||
location: eventLocation
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* The check listener for the event listeners container.
|
||||
*/
|
||||
_onCheck: function({ detail: { description, checked }, target }) {
|
||||
if (description == "item") {
|
||||
this.getItemForElement(target).attachment.checkboxState = checked;
|
||||
DebuggerController.Breakpoints.DOM.scheduleEventBreakpointsUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check all the event items in this group.
|
||||
this.items
|
||||
.filter(e => e.description == description)
|
||||
.forEach(e => this.callMethod("checkItem", e.target, checked));
|
||||
},
|
||||
|
||||
/**
|
||||
* The select listener for the event listeners container.
|
||||
*/
|
||||
_onClick: function({ target }) {
|
||||
// Changing the checkbox state is handled by the _onCheck event. Avoid
|
||||
// handling that again in this click event, so pass in "noSiblings"
|
||||
// when retrieving the target's item, to ignore the checkbox.
|
||||
let eventItem = this.getItemForElement(target, { noSiblings: true });
|
||||
if (eventItem) {
|
||||
let newState = eventItem.attachment.checkboxState ^= 1;
|
||||
this.callMethod("checkItem", eventItem.target, newState);
|
||||
}
|
||||
},
|
||||
|
||||
_eventCheckboxTooltip: "",
|
||||
_onSelectorString: "",
|
||||
_inSourceString: ""
|
||||
});
|
||||
|
||||
/**
|
||||
* Functions handling the global search UI.
|
||||
*/
|
||||
@ -2228,4 +2487,5 @@ LineResults.size = function() {
|
||||
*/
|
||||
DebuggerView.Sources = new SourcesView();
|
||||
DebuggerView.WatchExpressions = new WatchExpressionsView();
|
||||
DebuggerView.EventListeners = new EventListenersView();
|
||||
DebuggerView.GlobalSearch = new GlobalSearchView();
|
||||
|
@ -64,6 +64,7 @@ let DebuggerView = {
|
||||
this.StackFrames.initialize();
|
||||
this.Sources.initialize();
|
||||
this.WatchExpressions.initialize();
|
||||
this.EventListeners.initialize();
|
||||
this.GlobalSearch.initialize();
|
||||
this._initializeVariablesView();
|
||||
this._initializeEditor(deferred.resolve);
|
||||
@ -94,6 +95,7 @@ let DebuggerView = {
|
||||
this.StackFrames.destroy();
|
||||
this.Sources.destroy();
|
||||
this.WatchExpressions.destroy();
|
||||
this.EventListeners.destroy();
|
||||
this.GlobalSearch.destroy();
|
||||
this._destroyPanes();
|
||||
this._destroyEditor(deferred.resolve);
|
||||
@ -111,6 +113,9 @@ let DebuggerView = {
|
||||
this._instrumentsPane = document.getElementById("instruments-pane");
|
||||
this._instrumentsPaneToggleButton = document.getElementById("instruments-pane-toggle");
|
||||
|
||||
this._onTabSelect = this._onInstrumentsPaneTabSelect.bind(this);
|
||||
this._instrumentsPane.tabpanels.addEventListener("select", this._onTabSelect);
|
||||
|
||||
this._collapsePaneString = L10N.getStr("collapsePanes");
|
||||
this._expandPaneString = L10N.getStr("expandPanes");
|
||||
|
||||
@ -128,6 +133,8 @@ let DebuggerView = {
|
||||
Prefs.sourcesWidth = this._sourcesPane.getAttribute("width");
|
||||
Prefs.instrumentsWidth = this._instrumentsPane.getAttribute("width");
|
||||
|
||||
this._instrumentsPane.tabpanels.removeEventListener("select", this._onTabSelect);
|
||||
|
||||
this._sourcesPane = null;
|
||||
this._instrumentsPane = null;
|
||||
this._instrumentsPaneToggleButton = null;
|
||||
@ -406,6 +413,13 @@ let DebuggerView = {
|
||||
get instrumentsPaneHidden()
|
||||
this._instrumentsPane.hasAttribute("pane-collapsed"),
|
||||
|
||||
/**
|
||||
* Gets the currently selected tab in the instruments pane.
|
||||
* @return string
|
||||
*/
|
||||
get instrumentsPaneTab()
|
||||
this._instrumentsPane.selectedTab.id,
|
||||
|
||||
/**
|
||||
* Sets the instruments pane hidden or visible.
|
||||
*
|
||||
@ -415,8 +429,10 @@ let DebuggerView = {
|
||||
* - animated: true to display an animation on toggle
|
||||
* - delayed: true to wait a few cycles before toggle
|
||||
* - callback: a function to invoke when the toggle finishes
|
||||
* @param number aTabIndex [optional]
|
||||
* The index of the intended selected tab in the details pane.
|
||||
*/
|
||||
toggleInstrumentsPane: function(aFlags) {
|
||||
toggleInstrumentsPane: function(aFlags, aTabIndex) {
|
||||
let pane = this._instrumentsPane;
|
||||
let button = this._instrumentsPaneToggleButton;
|
||||
|
||||
@ -429,6 +445,10 @@ let DebuggerView = {
|
||||
button.setAttribute("pane-collapsed", "");
|
||||
button.setAttribute("tooltiptext", this._expandPaneString);
|
||||
}
|
||||
|
||||
if (aTabIndex !== undefined) {
|
||||
pane.selectedIndex = aTabIndex;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -443,7 +463,16 @@ let DebuggerView = {
|
||||
animated: true,
|
||||
delayed: true,
|
||||
callback: aCallback
|
||||
});
|
||||
}, 0);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles a tab selection event on the instruments pane.
|
||||
*/
|
||||
_onInstrumentsPaneTabSelect: function() {
|
||||
if (this._instrumentsPane.selectedTab.id == "events-tab") {
|
||||
DebuggerController.Breakpoints.DOM.scheduleEventListenersFetch();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -460,6 +489,7 @@ let DebuggerView = {
|
||||
this.StackFrames.empty();
|
||||
this.Sources.empty();
|
||||
this.Variables.empty();
|
||||
this.EventListeners.empty();
|
||||
|
||||
if (this.editor) {
|
||||
this.editor.setMode(SourceEditor.MODES.TEXT);
|
||||
@ -482,6 +512,7 @@ let DebuggerView = {
|
||||
Sources: null,
|
||||
Variables: null,
|
||||
WatchExpressions: null,
|
||||
EventListeners: null,
|
||||
editor: null,
|
||||
_editorSource: {},
|
||||
_loadingText: "",
|
||||
|
@ -10,14 +10,18 @@
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* Watch expressions view */
|
||||
/* Instruments pane view (watch expressions, variables, events...) */
|
||||
|
||||
#instruments-pane > tabpanels > tabpanel {
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
#expressions {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Toolbar */
|
||||
/* Toolbar controls */
|
||||
|
||||
.devtools-toolbarbutton:not([label]) > .toolbarbutton-text {
|
||||
display: none;
|
||||
|
@ -333,7 +333,7 @@
|
||||
</vbox>
|
||||
<splitter class="devtools-side-splitter"/>
|
||||
<deck id="editor-deck" flex="1" selectedIndex="0">
|
||||
<vbox id="editor" />
|
||||
<vbox id="editor"/>
|
||||
<vbox id="black-boxed-message" align="center">
|
||||
<label id="black-boxed-message-label">
|
||||
&debuggerUI.blackBoxMessage.label;
|
||||
@ -346,11 +346,24 @@
|
||||
</vbox>
|
||||
</deck>
|
||||
<splitter class="devtools-side-splitter"/>
|
||||
<vbox id="instruments-pane" hidden="true">
|
||||
<vbox id="expressions"/>
|
||||
<splitter class="devtools-horizontal-splitter"/>
|
||||
<vbox id="variables" flex="1"/>
|
||||
</vbox>
|
||||
<tabbox id="instruments-pane"
|
||||
class="devtools-sidebar-tabs"
|
||||
hidden="true">
|
||||
<tabs>
|
||||
<tab id="variables-tab" label="&debuggerUI.tabs.variables;"/>
|
||||
<tab id="events-tab" label="&debuggerUI.tabs.events;"/>
|
||||
</tabs>
|
||||
<tabpanels flex="1">
|
||||
<tabpanel id="variables-tabpanel">
|
||||
<vbox id="expressions"/>
|
||||
<splitter class="devtools-horizontal-splitter"/>
|
||||
<vbox id="variables" flex="1"/>
|
||||
</tabpanel>
|
||||
<tabpanel id="events-tabpanel">
|
||||
<vbox id="event-listeners" flex="1"/>
|
||||
</tabpanel>
|
||||
</tabpanels>
|
||||
</tabbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
|
@ -32,27 +32,31 @@ this.EXPORTED_SYMBOLS = ["SideMenuWidget"];
|
||||
* @param nsIDOMNode aNode
|
||||
* The element associated with the widget.
|
||||
* @param Object aOptions
|
||||
* - showArrows: Specifies if items in this container should display
|
||||
* horizontal arrows.
|
||||
* - showCheckboxes: Specifies if items in this container should display
|
||||
* checkboxes.
|
||||
* - theme: "light" or "dark", defaults to dark if falsy.
|
||||
* - showArrows: specifies if items should display horizontal arrows.
|
||||
* - showItemCheckboxes: specifies if items should display checkboxes.
|
||||
* - showGroupCheckboxes: specifies if groups should display checkboxes.
|
||||
*/
|
||||
this.SideMenuWidget = function SideMenuWidget(aNode, aOptions={}) {
|
||||
this.document = aNode.ownerDocument;
|
||||
this.window = this.document.defaultView;
|
||||
this._parent = aNode;
|
||||
|
||||
let { showArrows, showCheckboxes } = aOptions;
|
||||
let { theme, showArrows, showItemCheckboxes, showGroupCheckboxes } = aOptions;
|
||||
this._theme = theme || "dark";
|
||||
this._showArrows = showArrows || false;
|
||||
this._showCheckboxes = showCheckboxes || false;
|
||||
this._showItemCheckboxes = showItemCheckboxes || false;
|
||||
this._showGroupCheckboxes = showGroupCheckboxes || false;
|
||||
|
||||
// Create an internal scrollbox container.
|
||||
this._list = this.document.createElement("scrollbox");
|
||||
this._list.className = "side-menu-widget-container";
|
||||
this._list.setAttribute("flex", "1");
|
||||
this._list.setAttribute("orient", "vertical");
|
||||
this._list.setAttribute("with-arrow", showArrows);
|
||||
this._list.setAttribute("with-checkboxes", showCheckboxes);
|
||||
this._list.setAttribute("theme", this._theme);
|
||||
this._list.setAttribute("with-arrows", this._showArrows);
|
||||
this._list.setAttribute("with-item-checkboxes", this._showItemCheckboxes);
|
||||
this._list.setAttribute("with-group-checkboxes", this._showGroupCheckboxes);
|
||||
this._list.setAttribute("tabindex", "0");
|
||||
this._list.addEventListener("keypress", e => this.emit("keyPress", e), false);
|
||||
this._list.addEventListener("mousedown", e => this.emit("mousePress", e), false);
|
||||
@ -348,7 +352,7 @@ SideMenuWidget.prototype = {
|
||||
|
||||
let container = this.document.createElement("vbox");
|
||||
container.className = "side-menu-widget-empty-notice-container";
|
||||
container.setAttribute("align", "center");
|
||||
container.setAttribute("theme", this._theme);
|
||||
|
||||
let label = this.document.createElement("label");
|
||||
label.className = "plain side-menu-widget-empty-notice";
|
||||
@ -388,9 +392,14 @@ SideMenuWidget.prototype = {
|
||||
return cachedGroup;
|
||||
}
|
||||
|
||||
let group = new SideMenuGroup(this, aName);
|
||||
let group = new SideMenuGroup(this, aName, {
|
||||
theme: this._theme,
|
||||
showCheckbox: this._showGroupCheckboxes
|
||||
});
|
||||
|
||||
this._groupsByName.set(aName, group);
|
||||
group.insertSelfAt(this.sortedGroups ? group.findExpectedIndexForSelf() : -1);
|
||||
|
||||
return group;
|
||||
},
|
||||
|
||||
@ -408,13 +417,19 @@ SideMenuWidget.prototype = {
|
||||
* The attachement object.
|
||||
*/
|
||||
_getMenuItemForGroup: function(aGroup, aContents, aTooltip, aAttachment) {
|
||||
return new SideMenuItem(aGroup, aContents, aTooltip, this._showArrows, this._showCheckboxes, aAttachment);
|
||||
return new SideMenuItem(aGroup, aContents, aTooltip, aAttachment, {
|
||||
theme: this._theme,
|
||||
showArrow: this._showArrows,
|
||||
showCheckbox: this._showItemCheckboxes
|
||||
});
|
||||
},
|
||||
|
||||
window: null,
|
||||
document: null,
|
||||
_theme: "",
|
||||
_showArrows: false,
|
||||
_showCheckboxes: false,
|
||||
_showItemCheckboxes: false,
|
||||
_showGroupCheckboxes: false,
|
||||
_parent: null,
|
||||
_list: null,
|
||||
_boxObject: null,
|
||||
@ -437,8 +452,12 @@ SideMenuWidget.prototype = {
|
||||
* The widget to contain this menu item.
|
||||
* @param string aName
|
||||
* The string displayed in the container.
|
||||
* @param object aOptions [optional]
|
||||
* An object containing the following properties:
|
||||
* - theme: the theme colors, either "dark" or "light".
|
||||
* - showCheckbox: specifies if a checkbox should be displayed.
|
||||
*/
|
||||
function SideMenuGroup(aWidget, aName) {
|
||||
function SideMenuGroup(aWidget, aName, aOptions={}) {
|
||||
this.document = aWidget.document;
|
||||
this.window = aWidget.window;
|
||||
this.ownerView = aWidget;
|
||||
@ -456,6 +475,7 @@ function SideMenuGroup(aWidget, aName) {
|
||||
|
||||
let title = this._title = this.document.createElement("hbox");
|
||||
title.className = "side-menu-widget-group-title";
|
||||
title.setAttribute("theme", aOptions.theme);
|
||||
|
||||
let name = this._name = this.document.createElement("label");
|
||||
name.className = "plain name";
|
||||
@ -463,6 +483,13 @@ function SideMenuGroup(aWidget, aName) {
|
||||
name.setAttribute("crop", "end");
|
||||
name.setAttribute("flex", "1");
|
||||
|
||||
// Show a checkbox before the content.
|
||||
if (aOptions.showCheckbox) {
|
||||
let checkbox = this._checkbox = makeCheckbox(title, { description: aName });
|
||||
checkbox.className = "side-menu-widget-group-checkbox";
|
||||
checkbox.setAttribute("align", "start");
|
||||
}
|
||||
|
||||
title.appendChild(name);
|
||||
target.appendChild(title);
|
||||
target.appendChild(list);
|
||||
@ -471,6 +498,7 @@ function SideMenuGroup(aWidget, aName) {
|
||||
else {
|
||||
let target = this._target = this._list = this.document.createElement("vbox");
|
||||
target.className = "side-menu-widget-group side-menu-widget-group-list";
|
||||
target.setAttribute("theme", aOptions.theme);
|
||||
}
|
||||
}
|
||||
|
||||
@ -523,6 +551,7 @@ SideMenuGroup.prototype = {
|
||||
ownerView: null,
|
||||
identifier: "",
|
||||
_target: null,
|
||||
_checkbox: null,
|
||||
_title: null,
|
||||
_name: null,
|
||||
_list: null
|
||||
@ -537,37 +566,39 @@ SideMenuGroup.prototype = {
|
||||
* A tooltip attribute for the displayed item.
|
||||
* @param string | nsIDOMNode aContents
|
||||
* The string or node displayed in the container.
|
||||
* @param boolean aArrowFlag
|
||||
* True if a horizontal arrow should be shown.
|
||||
* @param boolean aCheckboxFlag
|
||||
* True if a checkbox should be shown.
|
||||
* @param object aAttachment [optional]
|
||||
* The attachment object.
|
||||
* @param object aOptions [optional]
|
||||
* An object containing the following properties:
|
||||
* - theme: the theme colors, either "dark" or "light".
|
||||
* - showArrow: specifies if a horizontal arrow should be displayed.
|
||||
* - showCheckbox: specifies if a checkbox should be displayed.
|
||||
*/
|
||||
function SideMenuItem(aGroup, aContents, aTooltip, aArrowFlag, aCheckboxFlag, aAttachment={}) {
|
||||
function SideMenuItem(aGroup, aContents, aTooltip, aAttachment={}, aOptions={}) {
|
||||
this.document = aGroup.document;
|
||||
this.window = aGroup.window;
|
||||
this.ownerView = aGroup;
|
||||
|
||||
if (aArrowFlag || aCheckboxFlag) {
|
||||
if (aOptions.showArrow || aOptions.showCheckbox) {
|
||||
let container = this._container = this.document.createElement("hbox");
|
||||
container.className = "side-menu-widget-item";
|
||||
container.setAttribute("tooltiptext", aTooltip);
|
||||
container.setAttribute("theme", aOptions.theme);
|
||||
|
||||
let target = this._target = this.document.createElement("vbox");
|
||||
target.className = "side-menu-widget-item-contents";
|
||||
|
||||
// Show a checkbox before the content.
|
||||
if (aCheckboxFlag) {
|
||||
let checkbox = this._checkbox = this._makeCheckbox(aAttachment);
|
||||
if (aOptions.showCheckbox) {
|
||||
let checkbox = this._checkbox = makeCheckbox(container, aAttachment);
|
||||
checkbox.className = "side-menu-widget-item-checkbox";
|
||||
checkbox.setAttribute("align", "start");
|
||||
container.appendChild(checkbox);
|
||||
}
|
||||
|
||||
container.appendChild(target);
|
||||
|
||||
// Show a horizontal arrow towards the content.
|
||||
if (aArrowFlag) {
|
||||
if (aOptions.showArrow) {
|
||||
let arrow = this._arrow = this.document.createElement("hbox");
|
||||
arrow.className = "side-menu-widget-item-arrow";
|
||||
container.appendChild(arrow);
|
||||
@ -577,6 +608,7 @@ function SideMenuItem(aGroup, aContents, aTooltip, aArrowFlag, aCheckboxFlag, aA
|
||||
else {
|
||||
let target = this._target = this._container = this.document.createElement("hbox");
|
||||
target.className = "side-menu-widget-item side-menu-widget-item-contents";
|
||||
target.setAttribute("theme", aOptions.theme);
|
||||
}
|
||||
|
||||
this._target.setAttribute("flex", "1");
|
||||
@ -588,40 +620,6 @@ SideMenuItem.prototype = {
|
||||
get _orderedMenuElementsArray() this.ownerView._orderedMenuElementsArray,
|
||||
get _itemsByElement() { return this.ownerView._itemsByElement; },
|
||||
|
||||
/**
|
||||
* Create the checkbox used when the checkbox flag is true. Emits a "check"
|
||||
* event whenever the checkbox is checked or unchecked by the user.
|
||||
*
|
||||
* @param Object aAttachment
|
||||
* The attachment object. The following properties are used:
|
||||
* - checkboxState: true for checked, false for unchecked
|
||||
8 - checkboxTooltip: The tooltip text of the checkbox
|
||||
*/
|
||||
_makeCheckbox: function (aAttachment) {
|
||||
let checkbox = this.document.createElement("checkbox");
|
||||
checkbox.className = "side-menu-widget-item-checkbox";
|
||||
checkbox.setAttribute("tooltiptext", aAttachment.checkboxTooltip);
|
||||
|
||||
if (aAttachment.checkboxState) {
|
||||
checkbox.setAttribute("checked", true);
|
||||
} else {
|
||||
checkbox.removeAttribute("checked");
|
||||
}
|
||||
|
||||
// Stop the toggling of the checkbox from selecting the list item.
|
||||
checkbox.addEventListener("mousedown", function (event) {
|
||||
event.stopPropagation();
|
||||
}, false);
|
||||
|
||||
checkbox.addEventListener("command", function (event) {
|
||||
ViewHelpers.dispatchEvent(checkbox, "check", {
|
||||
checked: checkbox.checked,
|
||||
});
|
||||
}, false);
|
||||
|
||||
return checkbox;
|
||||
},
|
||||
|
||||
/**
|
||||
* Inserts this item in the parent group at the specified index.
|
||||
*
|
||||
@ -656,11 +654,9 @@ SideMenuItem.prototype = {
|
||||
if (!this._checkbox) {
|
||||
throw new Error("Cannot check items that do not have checkboxes.");
|
||||
}
|
||||
if (aCheckState) {
|
||||
this._checkbox.setAttribute("checked", true);
|
||||
} else {
|
||||
this._checkbox.removeAttribute("checked");
|
||||
}
|
||||
// Don't set or remove the "checked" attribute, assign the property instead.
|
||||
// Otherwise, the "CheckboxStateChange" event will not be fired. XUL!!
|
||||
this._checkbox.checked = !!aCheckState;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -698,3 +694,43 @@ SideMenuItem.prototype = {
|
||||
_checkbox: null,
|
||||
_arrow: null
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a checkbox to a specified parent node. Emits a "check" event
|
||||
* whenever the checkbox is checked or unchecked by the user.
|
||||
*
|
||||
* @param nsIDOMNode aParentNode
|
||||
* The parent node to contain this checkbox.
|
||||
* @param object aOptions
|
||||
* An object containing some or all of the following properties:
|
||||
* - description: defaults to "item" if unspecified
|
||||
* - checkboxState: true for checked, false for unchecked
|
||||
* - checkboxTooltip: the tooltip text of the checkbox
|
||||
*/
|
||||
function makeCheckbox(aParentNode, aOptions) {
|
||||
let checkbox = aParentNode.ownerDocument.createElement("checkbox");
|
||||
checkbox.setAttribute("tooltiptext", aOptions.checkboxTooltip);
|
||||
|
||||
if (aOptions.checkboxState) {
|
||||
checkbox.setAttribute("checked", true);
|
||||
} else {
|
||||
checkbox.removeAttribute("checked");
|
||||
}
|
||||
|
||||
// Stop the toggling of the checkbox from selecting the list item.
|
||||
checkbox.addEventListener("mousedown", e => {
|
||||
e.stopPropagation();
|
||||
}, false);
|
||||
|
||||
// Emit an event from the checkbox when it is toggled. Don't listen for the
|
||||
// "command" event! It won't fire for programmatic changes. XUL!!
|
||||
checkbox.addEventListener("CheckboxStateChange", e => {
|
||||
ViewHelpers.dispatchEvent(checkbox, "check", {
|
||||
description: aOptions.description || "item",
|
||||
checked: checkbox.checked
|
||||
});
|
||||
}, false);
|
||||
|
||||
aParentNode.appendChild(checkbox);
|
||||
return checkbox;
|
||||
}
|
||||
|
@ -1271,6 +1271,7 @@ this.WidgetMethods = {
|
||||
* The matched item, or null if nothing is found.
|
||||
*/
|
||||
getItemForPredicate: function(aPredicate, aOwner = this) {
|
||||
// Recursively check the items in this widget for a predicate match.
|
||||
for (let [element, item] of aOwner._itemsByElement) {
|
||||
let match;
|
||||
if (aPredicate(item) && !element.hidden) {
|
||||
@ -1282,6 +1283,13 @@ this.WidgetMethods = {
|
||||
return match;
|
||||
}
|
||||
}
|
||||
// Also check the staged items. No need to do this recursively since
|
||||
// they're not even appended to the view yet.
|
||||
for (let { item } of this._stagedItems) {
|
||||
if (aPredicate(item)) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
@ -1349,6 +1357,14 @@ this.WidgetMethods = {
|
||||
return this.items.map(e => e._value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a list of attachments in this container, in the displayed order.
|
||||
* @return array
|
||||
*/
|
||||
get attachments() {
|
||||
return this.items.map(e => e.attachment);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a list of all the visible (non-hidden) items in this container,
|
||||
* in the displayed order
|
||||
|
@ -125,6 +125,11 @@ button that pretty prints the selected source. -->
|
||||
<!ENTITY debuggerUI.seMenuCondBreak "Add conditional breakpoint">
|
||||
<!ENTITY debuggerUI.seMenuCondBreak.key "B">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.instruments.*): This is the text that
|
||||
- appears in the debugger's instruments pane tabs. -->
|
||||
<!ENTITY debuggerUI.tabs.variables "Variables">
|
||||
<!ENTITY debuggerUI.tabs.events "Events">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.seMenuAddWatch): This is the text that
|
||||
- appears in the source editor context menu for adding an expression. -->
|
||||
<!ENTITY debuggerUI.seMenuAddWatch "Selection to watch expression">
|
||||
|
@ -61,7 +61,52 @@ noGlobalsText=No globals
|
||||
# when there are no scripts.
|
||||
noSourcesText=This page has no sources.
|
||||
|
||||
# LOCALIZATION NOTE (blackBoxCheckboxTooltip) = The tooltip text to display when
|
||||
# LOCALIZATION NOTE (noEventsTExt): The text to display in the events tab
|
||||
# when there are no events.
|
||||
noEventListenersText=No event listeners to display
|
||||
|
||||
# LOCALIZATION NOTE (eventCheckboxTooltip): The tooltip text to display when
|
||||
# the user hovers over the checkbox used to toggle an event breakpoint.
|
||||
eventCheckboxTooltip=Toggle breaking on this event
|
||||
|
||||
# LOCALIZATION NOTE (eventOnSelector): The text to display in the events tab
|
||||
# for every event item, between the event type and event selector.
|
||||
eventOnSelector=on
|
||||
|
||||
# LOCALIZATION NOTE (eventInSource): The text to display in the events tab
|
||||
# for every event item, between the event selector and listener's owner source.
|
||||
eventInSource=in
|
||||
|
||||
# LOCALIZATION NOTE (eventNodes): The text to display in the events tab when
|
||||
# an event is listened on more than one target node.
|
||||
eventNodes=%S nodes
|
||||
|
||||
# LOCALIZATION NOTE (*Events): The text to display in the events tab for
|
||||
# each group of sub-level event entries.
|
||||
animationEvents=Animation
|
||||
audioEvents=Audio
|
||||
batteryEvents=Battery
|
||||
clipboardEvents=Clipboard
|
||||
compositionEvents=Composition
|
||||
deviceEvents=Device
|
||||
displayEvents=Display
|
||||
dragAndDropEvents=Drag and Drop
|
||||
gamepadEvents=Gamepad
|
||||
indexedDBEvents=IndexedDB
|
||||
interactionEvents=Interaction
|
||||
keyboardEvents=Keyboard
|
||||
mediaEvents=HTML5 Media
|
||||
mouseEvents=Mouse
|
||||
mutationEvents=Mutation
|
||||
navigationEvents=Navigation
|
||||
pointerLockEvents=Pointer Lock
|
||||
sensorEvents=Sensor
|
||||
storageEvents=Storage
|
||||
timeEvents=Time
|
||||
touchEvents=Touch
|
||||
otherEvents=Other
|
||||
|
||||
# LOCALIZATION NOTE (blackBoxCheckboxTooltip): The tooltip text to display when
|
||||
# the user hovers over the checkbox used to toggle black boxing its associated
|
||||
# source.
|
||||
blackBoxCheckboxTooltip=Toggle black boxing
|
||||
|
@ -22,28 +22,26 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
#sources .side-menu-widget-item-checkbox {
|
||||
-moz-appearance: none;
|
||||
-moz-margin-end: -6px;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
transition: opacity .15s ease 0s;
|
||||
}
|
||||
|
||||
/* Only show the checkbox when the source is hovered over, is selected, or if it
|
||||
* is not checked. */
|
||||
.side-menu-widget-item:hover > .side-menu-widget-item-checkbox,
|
||||
.side-menu-widget-item.selected > .side-menu-widget-item-checkbox,
|
||||
.side-menu-widget-item-checkbox:not([checked]) {
|
||||
#sources .side-menu-widget-item:hover > .side-menu-widget-item-checkbox,
|
||||
#sources .side-menu-widget-item.selected > .side-menu-widget-item-checkbox,
|
||||
#sources .side-menu-widget-item-checkbox:not([checked]) {
|
||||
opacity: 1;
|
||||
transition: opacity .15s ease 0s;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox > .checkbox-spacer-box {
|
||||
#sources .side-menu-widget-item-checkbox > .checkbox-spacer-box {
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox > .checkbox-spacer-box > .checkbox-check {
|
||||
#sources .side-menu-widget-item-checkbox > .checkbox-spacer-box > .checkbox-check {
|
||||
-moz-appearance: none;
|
||||
background: none;
|
||||
background-image: url(itemToggle.png);
|
||||
@ -56,15 +54,15 @@
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox[checked] > .checkbox-spacer-box > .checkbox-check {
|
||||
#sources .side-menu-widget-item-checkbox[checked] > .checkbox-spacer-box > .checkbox-check {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-contents {
|
||||
#sources .side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-contents {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-contents > .dbg-breakpoint {
|
||||
#sources .side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-contents > .dbg-breakpoint {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -153,6 +151,17 @@
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
/* Instruments pane (watch expressions, variables, event listeners...) */
|
||||
|
||||
#instruments-pane > tabs > tab {
|
||||
min-height: 2em !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
#instruments-pane > tabpanels > tabpanel {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
/* Watch expressions view */
|
||||
|
||||
#expressions {
|
||||
@ -167,13 +176,35 @@
|
||||
.dbg-expression-arrow {
|
||||
width: 16px;
|
||||
height: auto;
|
||||
background: -moz-image-rect(url("chrome://browser/skin/devtools/commandline-icon.png"), 0, 32, 16, 16);
|
||||
background: -moz-image-rect(url(commandline-icon.png), 0, 32, 16, 16);
|
||||
}
|
||||
|
||||
.dbg-expression-input {
|
||||
-moz-padding-start: 2px !important;
|
||||
}
|
||||
|
||||
/* Event listeners view */
|
||||
|
||||
.dbg-event-listener {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.dbg-event-listener-type {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.dbg-event-listener-separator {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.dbg-event-listener-targets {
|
||||
color: #046;
|
||||
}
|
||||
|
||||
.dbg-event-listener-location {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* Searchbox and the search operations help panel */
|
||||
|
||||
.devtools-searchinput {
|
||||
@ -325,7 +356,7 @@
|
||||
transform: scale(1.75, 1.75);
|
||||
}
|
||||
|
||||
/* Toolbar Controls */
|
||||
/* Toolbar controls */
|
||||
|
||||
#resumption-panel-desc {
|
||||
width: 200px;
|
||||
|
@ -269,57 +269,74 @@
|
||||
|
||||
/* SideMenuWidget */
|
||||
|
||||
.side-menu-widget-container {
|
||||
.side-menu-widget-container[theme="dark"] {
|
||||
background: url(background-noise-toolbar.png), hsl(208,11%,27%);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrow=true]:-moz-locale-dir(ltr),
|
||||
.side-menu-widget-group[with-arrow=true]:-moz-locale-dir(ltr),
|
||||
.side-menu-widget-item[with-arrow=true]:-moz-locale-dir(ltr) {
|
||||
.side-menu-widget-container[theme="light"] {
|
||||
background: #fff;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrows=true]:-moz-locale-dir(ltr) {
|
||||
box-shadow: inset -1px 0 0 #222426;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrow=true]:-moz-locale-dir(rtl),
|
||||
.side-menu-widget-group[with-arrow=true]:-moz-locale-dir(rtl),
|
||||
.side-menu-widget-item[with-arrow=true]:-moz-locale-dir(rtl) {
|
||||
.side-menu-widget-container[with-arrows=true]:-moz-locale-dir(rtl) {
|
||||
box-shadow: inset 1px 0 0 #222426;
|
||||
}
|
||||
|
||||
.side-menu-widget-group-title {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.side-menu-widget-group-title[theme="dark"] {
|
||||
background-image: linear-gradient(#1f3e4f, #1b3243);
|
||||
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
|
||||
0 -2px 0 hsla(206,37%,4%,.05) inset,
|
||||
0 -1px 1px hsla(206,37%,4%,.1) inset;
|
||||
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
|
||||
padding: 4px;
|
||||
color: #f5f7fa;
|
||||
transition-property: color, text-shadow;
|
||||
transition-duration: 0.3s;
|
||||
}
|
||||
|
||||
.side-menu-widget-group:hover > .side-menu-widget-group-title {
|
||||
text-shadow: 0 0 1px #cfcfcf;
|
||||
color: #fff;
|
||||
.side-menu-widget-group-title[theme="light"] {
|
||||
background-image: linear-gradient(#fff, #eee);
|
||||
}
|
||||
|
||||
.side-menu-widget-item {
|
||||
.side-menu-widget-group-checkbox {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="dark"] {
|
||||
border-top: 1px solid hsla(210,8%,5%,.25);
|
||||
border-bottom: 1px solid hsla(210,16%,76%,.1);
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.side-menu-widget-item:last-of-type {
|
||||
.side-menu-widget-item[theme="light"] {
|
||||
border-top: 1px solid hsla(210,8%,75%,.25);
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="dark"]:last-of-type {
|
||||
box-shadow: inset 0 -1px 0 hsla(210,8%,5%,.25);
|
||||
}
|
||||
|
||||
.side-menu-widget-item.selected {
|
||||
.side-menu-widget-item[theme="light"]:last-of-type {
|
||||
box-shadow: inset 0 -1px 0 hsla(210,8%,75%,.25);
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="dark"].selected {
|
||||
background: linear-gradient(hsl(206,61%,40%), hsl(206,61%,31%)) repeat-x top left !important;
|
||||
box-shadow: inset 0 1px 0 hsla(210,40%,83%,.15);
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="light"].selected {
|
||||
/* Nothing here yet */
|
||||
}
|
||||
|
||||
.side-menu-widget-item.selected > .side-menu-widget-item-arrow {
|
||||
background-size: auto, 1px 100%;
|
||||
background-repeat: no-repeat;
|
||||
@ -337,7 +354,6 @@
|
||||
|
||||
.side-menu-widget-item-label {
|
||||
padding: 4px 0px;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-arrow {
|
||||
@ -345,6 +361,11 @@
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
-moz-margin-start: 4px;
|
||||
-moz-margin-end: -6px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-other {
|
||||
background: url(background-noise-toolbar.png), hsla(208,11%,27%, 0.65);
|
||||
}
|
||||
@ -365,10 +386,19 @@
|
||||
}
|
||||
|
||||
.side-menu-widget-empty-notice-container {
|
||||
background: url(background-noise-toolbar.png), hsl(208,11%,27%);
|
||||
padding: 12px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.side-menu-widget-empty-notice-container[theme="dark"] {
|
||||
background: url(background-noise-toolbar.png), hsl(208,11%,27%);
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.side-menu-widget-empty-notice-container[theme="light"] {
|
||||
background: #fff;
|
||||
padding: 4px 8px;
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
/* VariablesView */
|
||||
|
@ -24,24 +24,22 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
#sources .side-menu-widget-item-checkbox {
|
||||
-moz-appearance: none;
|
||||
-moz-margin-end: -6px;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
transition: opacity .15s ease-out 0s;
|
||||
}
|
||||
|
||||
/* Only show the checkbox when the source is hovered over, is selected, or if it
|
||||
* is not checked. */
|
||||
.side-menu-widget-item:hover > .side-menu-widget-item-checkbox,
|
||||
.side-menu-widget-item.selected > .side-menu-widget-item-checkbox,
|
||||
.side-menu-widget-item-checkbox:not([checked]) {
|
||||
#sources .side-menu-widget-item:hover > .side-menu-widget-item-checkbox,
|
||||
#sources .side-menu-widget-item.selected > .side-menu-widget-item-checkbox,
|
||||
#sources .side-menu-widget-item-checkbox:not([checked]) {
|
||||
opacity: 1;
|
||||
transition: opacity .15s ease-out 0s;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox > .checkbox-check {
|
||||
#sources .side-menu-widget-item-checkbox > .checkbox-check {
|
||||
-moz-appearance: none;
|
||||
background: none;
|
||||
background-image: url(itemToggle.png);
|
||||
@ -54,15 +52,15 @@
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox[checked] > .checkbox-check {
|
||||
#sources .side-menu-widget-item-checkbox[checked] > .checkbox-check {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-contents {
|
||||
#sources .side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-contents {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-contents > .dbg-breakpoint {
|
||||
#sources .side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-contents > .dbg-breakpoint {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -151,6 +149,17 @@
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
/* Instruments pane (watch expressions, variables, event listeners...) */
|
||||
|
||||
#instruments-pane > tabs > tab {
|
||||
min-height: 2em !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
#instruments-pane > tabpanels > tabpanel {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
/* Watch expressions view */
|
||||
|
||||
#expressions {
|
||||
@ -165,13 +174,35 @@
|
||||
.dbg-expression-arrow {
|
||||
width: 16px;
|
||||
height: auto;
|
||||
background: -moz-image-rect(url("chrome://browser/skin/devtools/commandline-icon.png"), 0, 32, 16, 16);
|
||||
background: -moz-image-rect(url(commandline-icon.png), 0, 32, 16, 16);
|
||||
}
|
||||
|
||||
.dbg-expression-input {
|
||||
-moz-padding-start: 2px !important;
|
||||
}
|
||||
|
||||
/* Event listeners view */
|
||||
|
||||
.dbg-event-listener {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.dbg-event-listener-type {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.dbg-event-listener-separator {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.dbg-event-listener-targets {
|
||||
color: #046;
|
||||
}
|
||||
|
||||
.dbg-event-listener-location {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* Searchbox and the search operations help panel */
|
||||
|
||||
.devtools-searchinput {
|
||||
@ -323,7 +354,7 @@
|
||||
transform: scale(1.75, 1.75);
|
||||
}
|
||||
|
||||
/* Toolbar Controls */
|
||||
/* Toolbar controls */
|
||||
|
||||
#resumption-panel-desc {
|
||||
width: 200px;
|
||||
|
@ -269,57 +269,74 @@
|
||||
|
||||
/* SideMenuWidget */
|
||||
|
||||
.side-menu-widget-container {
|
||||
.side-menu-widget-container[theme="dark"] {
|
||||
background: url(background-noise-toolbar.png), hsl(208,11%,27%);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrow=true]:-moz-locale-dir(ltr),
|
||||
.side-menu-widget-group[with-arrow=true]:-moz-locale-dir(ltr),
|
||||
.side-menu-widget-item[with-arrow=true]:-moz-locale-dir(ltr) {
|
||||
.side-menu-widget-container[theme="light"] {
|
||||
background: #fff;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrows=true]:-moz-locale-dir(ltr) {
|
||||
box-shadow: inset -1px 0 0 #222426;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrow=true]:-moz-locale-dir(rtl),
|
||||
.side-menu-widget-group[with-arrow=true]:-moz-locale-dir(rtl),
|
||||
.side-menu-widget-item[with-arrow=true]:-moz-locale-dir(rtl) {
|
||||
.side-menu-widget-container[with-arrows=true]:-moz-locale-dir(rtl) {
|
||||
box-shadow: inset 1px 0 0 #222426;
|
||||
}
|
||||
|
||||
.side-menu-widget-group-title {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.side-menu-widget-group-title[theme="dark"] {
|
||||
background-image: linear-gradient(#1f3e4f, #1b3243);
|
||||
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
|
||||
0 -2px 0 hsla(206,37%,4%,.05) inset,
|
||||
0 -1px 1px hsla(206,37%,4%,.1) inset;
|
||||
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
|
||||
padding: 4px;
|
||||
color: #f5f7fa;
|
||||
transition-property: color, text-shadow;
|
||||
transition-duration: 0.3s;
|
||||
}
|
||||
|
||||
.side-menu-widget-group:hover > .side-menu-widget-group-title {
|
||||
text-shadow: 0 0 1px #cfcfcf;
|
||||
color: #fff;
|
||||
.side-menu-widget-group-title[theme="light"] {
|
||||
background-image: linear-gradient(#fff, #eee);
|
||||
}
|
||||
|
||||
.side-menu-widget-item {
|
||||
.side-menu-widget-group-checkbox {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="dark"] {
|
||||
border-top: 1px solid hsla(210,8%,5%,.25);
|
||||
border-bottom: 1px solid hsla(210,16%,76%,.1);
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.side-menu-widget-item:last-of-type {
|
||||
.side-menu-widget-item[theme="light"] {
|
||||
border-top: 1px solid hsla(210,8%,75%,.25);
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="dark"]:last-of-type {
|
||||
box-shadow: inset 0 -1px 0 hsla(210,8%,5%,.25);
|
||||
}
|
||||
|
||||
.side-menu-widget-item.selected {
|
||||
.side-menu-widget-item[theme="light"]:last-of-type {
|
||||
box-shadow: inset 0 -1px 0 hsla(210,8%,75%,.25);
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="dark"].selected {
|
||||
background: linear-gradient(hsl(206,61%,40%), hsl(206,61%,31%)) repeat-x top left !important;
|
||||
box-shadow: inset 0 1px 0 hsla(210,40%,83%,.15);
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="light"].selected {
|
||||
/* Nothing here yet */
|
||||
}
|
||||
|
||||
.side-menu-widget-item.selected > .side-menu-widget-item-arrow {
|
||||
background-size: auto, 1px 100%;
|
||||
background-repeat: no-repeat;
|
||||
@ -337,7 +354,6 @@
|
||||
|
||||
.side-menu-widget-item-label {
|
||||
padding: 4px 0px;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-arrow {
|
||||
@ -345,6 +361,11 @@
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
-moz-margin-start: 4px;
|
||||
-moz-margin-end: -6px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-other {
|
||||
background: url(background-noise-toolbar.png), hsla(208,11%,27%, 0.65);
|
||||
}
|
||||
@ -365,10 +386,19 @@
|
||||
}
|
||||
|
||||
.side-menu-widget-empty-notice-container {
|
||||
background: url(background-noise-toolbar.png), hsl(208,11%,27%);
|
||||
padding: 12px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.side-menu-widget-empty-notice-container[theme="dark"] {
|
||||
background: url(background-noise-toolbar.png), hsl(208,11%,27%);
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.side-menu-widget-empty-notice-container[theme="light"] {
|
||||
background: #fff;
|
||||
padding: 4px 8px;
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
/* VariablesView */
|
||||
|
@ -22,7 +22,7 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
#sources .side-menu-widget-item-checkbox {
|
||||
-moz-appearance: none;
|
||||
-moz-margin-end: -6px;
|
||||
padding: 0;
|
||||
@ -32,14 +32,14 @@
|
||||
|
||||
/* Only show the checkbox when the source is hovered over, is selected, or if it
|
||||
* is not checked. */
|
||||
.side-menu-widget-item:hover > .side-menu-widget-item-checkbox,
|
||||
.side-menu-widget-item.selected > .side-menu-widget-item-checkbox,
|
||||
.side-menu-widget-item-checkbox:not([checked]) {
|
||||
#sources .side-menu-widget-item:hover > .side-menu-widget-item-checkbox,
|
||||
#sources .side-menu-widget-item.selected > .side-menu-widget-item-checkbox,
|
||||
#sources .side-menu-widget-item-checkbox:not([checked]) {
|
||||
opacity: 1;
|
||||
transition: opacity .15s ease-out 0s;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox > .checkbox-check {
|
||||
#sources .side-menu-widget-item-checkbox > .checkbox-check {
|
||||
-moz-appearance: none;
|
||||
background: none;
|
||||
background-image: url(itemToggle.png);
|
||||
@ -52,15 +52,15 @@
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox[checked] > .checkbox-check {
|
||||
#sources .side-menu-widget-item-checkbox[checked] > .checkbox-check {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-contents {
|
||||
#sources .side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-contents {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-contents > .dbg-breakpoint {
|
||||
#sources .side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-contents > .dbg-breakpoint {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -149,6 +149,17 @@
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
/* Instruments pane (watch expressions, variables, event listeners...) */
|
||||
|
||||
#instruments-pane > tabs > tab {
|
||||
min-height: 2em !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
#instruments-pane > tabpanels > tabpanel {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
/* Watch expressions view */
|
||||
|
||||
#expressions {
|
||||
@ -163,13 +174,35 @@
|
||||
.dbg-expression-arrow {
|
||||
width: 16px;
|
||||
height: auto;
|
||||
background: -moz-image-rect(url("chrome://browser/skin/devtools/commandline-icon.png"), 0, 32, 16, 16);
|
||||
background: -moz-image-rect(url(commandline-icon.png), 0, 32, 16, 16);
|
||||
}
|
||||
|
||||
.dbg-expression-input {
|
||||
-moz-padding-start: 2px !important;
|
||||
}
|
||||
|
||||
/* Event listeners view */
|
||||
|
||||
.dbg-event-listener {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.dbg-event-listener-type {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.dbg-event-listener-separator {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.dbg-event-listener-targets {
|
||||
color: #046;
|
||||
}
|
||||
|
||||
.dbg-event-listener-location {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* Searchbox and the search operations help panel */
|
||||
|
||||
.devtools-searchinput {
|
||||
@ -321,7 +354,7 @@
|
||||
transform: scale(1.75, 1.75);
|
||||
}
|
||||
|
||||
/* Toolbar Controls */
|
||||
/* Toolbar controls */
|
||||
|
||||
#resumption-panel-desc {
|
||||
width: 200px;
|
||||
|
@ -273,57 +273,74 @@
|
||||
|
||||
/* SideMenuWidget */
|
||||
|
||||
.side-menu-widget-container {
|
||||
.side-menu-widget-container[theme="dark"] {
|
||||
background: url(background-noise-toolbar.png), hsl(208,11%,27%);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrow=true]:-moz-locale-dir(ltr),
|
||||
.side-menu-widget-group[with-arrow=true]:-moz-locale-dir(ltr),
|
||||
.side-menu-widget-item[with-arrow=true]:-moz-locale-dir(ltr) {
|
||||
.side-menu-widget-container[theme="light"] {
|
||||
background: #fff;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrows=true]:-moz-locale-dir(ltr) {
|
||||
box-shadow: inset -1px 0 0 #222426;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrow=true]:-moz-locale-dir(rtl),
|
||||
.side-menu-widget-group[with-arrow=true]:-moz-locale-dir(rtl),
|
||||
.side-menu-widget-item[with-arrow=true]:-moz-locale-dir(rtl) {
|
||||
.side-menu-widget-container[with-arrows=true]:-moz-locale-dir(rtl) {
|
||||
box-shadow: inset 1px 0 0 #222426;
|
||||
}
|
||||
|
||||
.side-menu-widget-group-title {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.side-menu-widget-group-title[theme="dark"] {
|
||||
background-image: linear-gradient(#1f3e4f, #1b3243);
|
||||
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
|
||||
0 -2px 0 hsla(206,37%,4%,.05) inset,
|
||||
0 -1px 1px hsla(206,37%,4%,.1) inset;
|
||||
text-shadow: 0 -1px 0 hsla(210,8%,5%,.45);
|
||||
padding: 4px;
|
||||
color: #f5f7fa;
|
||||
transition-property: color, text-shadow;
|
||||
transition-duration: 0.3s;
|
||||
}
|
||||
|
||||
.side-menu-widget-group:hover > .side-menu-widget-group-title {
|
||||
text-shadow: 0 0 1px #cfcfcf;
|
||||
color: #fff;
|
||||
.side-menu-widget-group-title[theme="light"] {
|
||||
background-image: linear-gradient(#fff, #eee);
|
||||
}
|
||||
|
||||
.side-menu-widget-item {
|
||||
.side-menu-widget-group-checkbox {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="dark"] {
|
||||
border-top: 1px solid hsla(210,8%,5%,.25);
|
||||
border-bottom: 1px solid hsla(210,16%,76%,.1);
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.side-menu-widget-item:last-of-type {
|
||||
.side-menu-widget-item[theme="light"] {
|
||||
border-top: 1px solid hsla(210,8%,75%,.25);
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="dark"]:last-of-type {
|
||||
box-shadow: inset 0 -1px 0 hsla(210,8%,5%,.25);
|
||||
}
|
||||
|
||||
.side-menu-widget-item.selected {
|
||||
.side-menu-widget-item[theme="light"]:last-of-type {
|
||||
box-shadow: inset 0 -1px 0 hsla(210,8%,75%,.25);
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="dark"].selected {
|
||||
background: linear-gradient(hsl(206,61%,40%), hsl(206,61%,31%)) repeat-x top left !important;
|
||||
box-shadow: inset 0 1px 0 hsla(210,40%,83%,.15);
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="light"].selected {
|
||||
/* Nothing here yet */
|
||||
}
|
||||
|
||||
.side-menu-widget-item.selected > .side-menu-widget-item-arrow {
|
||||
background-size: auto, 1px 100%;
|
||||
background-repeat: no-repeat;
|
||||
@ -341,7 +358,6 @@
|
||||
|
||||
.side-menu-widget-item-label {
|
||||
padding: 4px 0px;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-arrow {
|
||||
@ -349,6 +365,11 @@
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
-moz-margin-start: 4px;
|
||||
-moz-margin-end: -6px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-other {
|
||||
background: url(background-noise-toolbar.png), hsla(208,11%,27%, 0.65);
|
||||
}
|
||||
@ -368,10 +389,19 @@
|
||||
}
|
||||
|
||||
.side-menu-widget-empty-notice-container {
|
||||
background: url(background-noise-toolbar.png), hsl(208,11%,27%);
|
||||
padding: 12px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.side-menu-widget-empty-notice-container[theme="dark"] {
|
||||
background: url(background-noise-toolbar.png), hsl(208,11%,27%);
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.side-menu-widget-empty-notice-container[theme="light"] {
|
||||
background: #fff;
|
||||
padding: 4px 8px;
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
/* VariablesView */
|
||||
|
Loading…
Reference in New Issue
Block a user