зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1336301 - Styles that are applied directly to the select element should be forwarded to the popup. r=mconley
MozReview-Commit-ID: 29DjcUUqEkx --HG-- extra : rebase_source : 97970d2e8f1b6527caa2767b06ddf110a2478195
This commit is contained in:
Родитель
4c8c97a8e9
Коммит
7d9b3b83c6
|
@ -97,6 +97,17 @@ const PAGECONTENT_COLORS =
|
|||
' <option value="Seven" selected="true">{"unstyled": "true"}</option>' +
|
||||
"</select></body></html>";
|
||||
|
||||
const PAGECONTENT_COLORS_ON_SELECT =
|
||||
"<html><head><style>" +
|
||||
" #one { background-color: #7E3A3A; color: #fff }" +
|
||||
"</style>" +
|
||||
"<body><select id='one'>" +
|
||||
' <option value="One">{"color": "rgb(255, 255, 255)", "backgroundColor": "transparent"}</option>' +
|
||||
' <option value="Two">{"color": "rgb(255, 255, 255)", "backgroundColor": "transparent"}</option>' +
|
||||
' <option value="Three">{"color": "rgb(255, 255, 255)", "backgroundColor": "transparent"}</option>' +
|
||||
' <option value="Four" selected="true">{"end": "true"}</option>' +
|
||||
"</select></body></html>";
|
||||
|
||||
function openSelectPopup(selectPopup, mode = "key", selector = "select", win = window) {
|
||||
let popupShownPromise = BrowserTestUtils.waitForEvent(selectPopup, "popupshown");
|
||||
|
||||
|
@ -746,7 +757,8 @@ add_task(function* test_somehidden() {
|
|||
yield BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
||||
add_task(function* test_colors_applied_to_popup() {
|
||||
// This test checks when a <select> element has styles applied to <option>s within it.
|
||||
add_task(function* test_colors_applied_to_popup_items() {
|
||||
const pageUrl = "data:text/html," + escape(PAGECONTENT_COLORS);
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
|
||||
|
||||
|
@ -798,3 +810,66 @@ add_task(function* test_colors_applied_to_popup() {
|
|||
yield hideSelectPopup(selectPopup, "escape");
|
||||
yield BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
||||
// This test checks when a <select> element has styles applied to itself.
|
||||
add_task(function* test_colors_applied_to_popup() {
|
||||
const pageUrl = "data:text/html," + escape(PAGECONTENT_COLORS_ON_SELECT);
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
|
||||
|
||||
let menulist = document.getElementById("ContentSelectDropdown");
|
||||
let selectPopup = menulist.menupopup;
|
||||
|
||||
let popupShownPromise = BrowserTestUtils.waitForEvent(selectPopup, "popupshown");
|
||||
yield BrowserTestUtils.synthesizeMouseAtCenter("#one", { type: "mousedown" }, gBrowser.selectedBrowser);
|
||||
yield popupShownPromise;
|
||||
|
||||
// The label contains a JSON string of the expected colors for
|
||||
// `color` and `background-color`.
|
||||
is(selectPopup.parentNode.itemCount, 4, "Correct number of items");
|
||||
let child = selectPopup.firstChild;
|
||||
let idx = 1;
|
||||
|
||||
is(getComputedStyle(selectPopup).color, "rgb(255, 255, 255)",
|
||||
"popup has expected foreground color");
|
||||
is(getComputedStyle(selectPopup).backgroundColor, "rgb(126, 58, 58)",
|
||||
"popup has expected background color");
|
||||
|
||||
ok(!child.selected, "The first child should not be selected");
|
||||
while (child) {
|
||||
let expected = JSON.parse(child.label);
|
||||
|
||||
for (let color of Object.keys(expected)) {
|
||||
if (color.toLowerCase().includes("color") &&
|
||||
!expected[color].startsWith("rgb")) {
|
||||
// Need to convert system color to RGB color.
|
||||
let textarea = document.createElementNS("http://www.w3.org/1999/xhtml", "textarea");
|
||||
textarea.style.color = expected[color];
|
||||
expected[color] = getComputedStyle(textarea).color;
|
||||
}
|
||||
}
|
||||
|
||||
// Press Down to move the selected item to the next item in the
|
||||
// list and check the colors of this item when it's not selected.
|
||||
EventUtils.synthesizeKey("KEY_ArrowDown", { code: "ArrowDown" });
|
||||
|
||||
if (expected.end) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (expected.unstyled) {
|
||||
ok(!child.hasAttribute("customoptionstyling"),
|
||||
`Item ${idx} should not have any custom option styling`);
|
||||
} else {
|
||||
is(getComputedStyle(child).color, expected.color,
|
||||
"Item " + (idx) + " has correct foreground color");
|
||||
is(getComputedStyle(child).backgroundColor, expected.backgroundColor,
|
||||
"Item " + (idx) + " has correct background color");
|
||||
}
|
||||
|
||||
idx++;
|
||||
child = child.nextSibling;
|
||||
}
|
||||
|
||||
yield hideSelectPopup(selectPopup, "escape");
|
||||
yield BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
|
|
@ -1081,7 +1081,9 @@
|
|||
let menulist = document.getElementById(this.getAttribute("selectmenulist"));
|
||||
menulist.menupopup.style.direction = data.direction;
|
||||
this._selectParentHelper.populate(menulist, data.options, data.selectedIndex, this._fullZoom,
|
||||
data.uaBackgroundColor, data.uaColor);
|
||||
data.uaBackgroundColor, data.uaColor,
|
||||
data.uaSelectBackgroundColor, data.uaSelectColor,
|
||||
data.selectBackgroundColor, data.selectColor);
|
||||
this._selectParentHelper.open(this, menulist, data.rect, data.isOpenedViaTouch);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -472,7 +472,9 @@
|
|||
let zoom = Services.prefs.getBoolPref("browser.zoom.full") ||
|
||||
this.isSyntheticDocument ? this._fullZoom : this._textZoom;
|
||||
this._selectParentHelper.populate(menulist, data.options, data.selectedIndex,
|
||||
zoom, data.uaBackgroundColor, data.uaColor);
|
||||
zoom, data.uaBackgroundColor, data.uaColor,
|
||||
data.uaSelectBackgroundColor, data.uaSelectColor,
|
||||
data.selectBackgroundColor, data.selectColor);
|
||||
this._selectParentHelper.open(this, menulist, data.rect, data.isOpenedViaTouch);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -36,8 +36,12 @@ this.SelectContentHelper = function(aElement, aOptions, aGlobal) {
|
|||
this.global = aGlobal;
|
||||
this.closedWithEnter = false;
|
||||
this.isOpenedViaTouch = aOptions.isOpenedViaTouch;
|
||||
this._selectBackgroundColor = null;
|
||||
this._selectColor = null;
|
||||
this._uaBackgroundColor = null;
|
||||
this._uaColor = null;
|
||||
this._uaSelectBackgroundColor = null;
|
||||
this._uaSelectColor = null;
|
||||
this.init();
|
||||
this.showDropDown();
|
||||
this._updateTimer = new DeferredTask(this._update.bind(this), 0);
|
||||
|
@ -88,14 +92,21 @@ this.SelectContentHelper.prototype = {
|
|||
showDropDown() {
|
||||
this.element.openInParentProcess = true;
|
||||
let rect = this._getBoundingContentRect();
|
||||
let computedStyles = getComputedStyles(this.element);
|
||||
this._selectBackgroundColor = computedStyles.backgroundColor;
|
||||
this._selectColor = computedStyles.color;
|
||||
this.global.sendAsyncMessage("Forms:ShowDropDown", {
|
||||
rect,
|
||||
options: this._buildOptionList(),
|
||||
selectedIndex: this.element.selectedIndex,
|
||||
direction: getComputedStyles(this.element).direction,
|
||||
direction: computedStyles.direction,
|
||||
isOpenedViaTouch: this.isOpenedViaTouch,
|
||||
options: this._buildOptionList(),
|
||||
rect,
|
||||
selectedIndex: this.element.selectedIndex,
|
||||
selectBackgroundColor: this._selectBackgroundColor,
|
||||
selectColor: this._selectColor,
|
||||
uaBackgroundColor: this.uaBackgroundColor,
|
||||
uaColor: this.uaColor,
|
||||
uaSelectBackgroundColor: this.uaSelectBackgroundColor,
|
||||
uaSelectColor: this.uaSelectColor
|
||||
});
|
||||
gOpen = true;
|
||||
},
|
||||
|
@ -114,8 +125,12 @@ this.SelectContentHelper.prototype = {
|
|||
this.global.sendAsyncMessage("Forms:UpdateDropDown", {
|
||||
options: this._buildOptionList(),
|
||||
selectedIndex: this.element.selectedIndex,
|
||||
selectBackgroundColor: this._selectBackgroundColor,
|
||||
selectColor: this._selectColor,
|
||||
uaBackgroundColor: this.uaBackgroundColor,
|
||||
uaColor: this.uaColor,
|
||||
uaSelectBackgroundColor: this.uaSelectBackgroundColor,
|
||||
uaSelectColor: this.uaSelectColor
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -123,12 +138,18 @@ this.SelectContentHelper.prototype = {
|
|||
// This is used to skip applying the custom color if it matches
|
||||
// the user agent values.
|
||||
_calculateUAColors() {
|
||||
let dummy = this.element.ownerDocument.createElement("option");
|
||||
dummy.style.color = "-moz-comboboxtext";
|
||||
dummy.style.backgroundColor = "-moz-combobox";
|
||||
let dummyCS = this.element.ownerGlobal.getComputedStyle(dummy);
|
||||
this._uaBackgroundColor = dummyCS.backgroundColor;
|
||||
this._uaColor = dummyCS.color;
|
||||
let dummyOption = this.element.ownerDocument.createElement("option");
|
||||
dummyOption.style.color = "-moz-comboboxtext";
|
||||
dummyOption.style.backgroundColor = "-moz-combobox";
|
||||
let optionCS = this.element.ownerGlobal.getComputedStyle(dummyOption);
|
||||
this._uaBackgroundColor = optionCS.backgroundColor;
|
||||
this._uaColor = optionCS.color;
|
||||
let dummySelect = this.element.ownerDocument.createElement("select");
|
||||
dummySelect.style.color = "-moz-fieldtext";
|
||||
dummySelect.style.backgroundColor = "-moz-field";
|
||||
let selectCS = this.element.ownerGlobal.getComputedStyle(dummySelect);
|
||||
this._uaSelectBackgroundColor = selectCS.backgroundColor;
|
||||
this._uaSelectColor = selectCS.color;
|
||||
},
|
||||
|
||||
get uaBackgroundColor() {
|
||||
|
@ -145,6 +166,20 @@ this.SelectContentHelper.prototype = {
|
|||
return this._uaColor;
|
||||
},
|
||||
|
||||
get uaSelectBackgroundColor() {
|
||||
if (!this._selectBackgroundColor) {
|
||||
this._calculateUAColors();
|
||||
}
|
||||
return this._uaSelectBackgroundColor;
|
||||
},
|
||||
|
||||
get uaSelectColor() {
|
||||
if (!this._selectBackgroundColor) {
|
||||
this._calculateUAColors();
|
||||
}
|
||||
return this._uaSelectColor;
|
||||
},
|
||||
|
||||
dispatchMouseEvent(win, target, eventName) {
|
||||
let mouseEvent = new win.MouseEvent(eventName, {
|
||||
view: win,
|
||||
|
|
|
@ -25,7 +25,8 @@ var closedWithEnter = false;
|
|||
var selectRect;
|
||||
|
||||
this.SelectParentHelper = {
|
||||
populate(menulist, items, selectedIndex, zoom, uaBackgroundColor, uaColor) {
|
||||
populate(menulist, items, selectedIndex, zoom, uaBackgroundColor, uaColor,
|
||||
uaSelectBackgroundColor, uaSelectColor, selectBackgroundColor, selectColor) {
|
||||
// Clear the current contents of the popup
|
||||
menulist.menupopup.textContent = "";
|
||||
let stylesheet = menulist.querySelector("#ContentSelectDropdownScopedStylesheet");
|
||||
|
@ -33,10 +34,29 @@ this.SelectParentHelper = {
|
|||
stylesheet.remove();
|
||||
}
|
||||
|
||||
let doc = menulist.ownerDocument;
|
||||
stylesheet = doc.createElementNS("http://www.w3.org/1999/xhtml", "style");
|
||||
stylesheet.setAttribute("id", "ContentSelectDropdownScopedStylesheet");
|
||||
stylesheet.scoped = true;
|
||||
stylesheet.hidden = true;
|
||||
stylesheet = menulist.appendChild(stylesheet);
|
||||
|
||||
let sheet = stylesheet.sheet;
|
||||
if (selectBackgroundColor != uaSelectBackgroundColor ||
|
||||
selectColor != uaSelectColor) {
|
||||
sheet.insertRule(`menupopup {
|
||||
background-color: ${selectBackgroundColor};
|
||||
color: ${selectColor};
|
||||
}`, 0);
|
||||
menulist.menupopup.setAttribute("customoptionstyling", "true");
|
||||
} else {
|
||||
menulist.menupopup.removeAttribute("customoptionstyling");
|
||||
}
|
||||
|
||||
currentZoom = zoom;
|
||||
currentMenulist = menulist;
|
||||
populateChildren(menulist, items, selectedIndex, zoom,
|
||||
uaBackgroundColor, uaColor);
|
||||
uaBackgroundColor, uaColor, sheet);
|
||||
},
|
||||
|
||||
open(browser, menulist, rect, isOpenedViaTouch) {
|
||||
|
@ -147,8 +167,11 @@ this.SelectParentHelper = {
|
|||
let selectedIndex = msg.data.selectedIndex;
|
||||
let uaBackgroundColor = msg.data.uaBackgroundColor;
|
||||
let uaColor = msg.data.uaColor;
|
||||
let selectBackgroundColor = msg.data.selectBackgroundColor;
|
||||
let selectColor = msg.data.selectColor;
|
||||
this.populate(currentMenulist, options, selectedIndex,
|
||||
currentZoom, uaBackgroundColor, uaColor);
|
||||
currentZoom, uaBackgroundColor, uaColor,
|
||||
selectBackgroundColor, selectColor);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -177,20 +200,11 @@ this.SelectParentHelper = {
|
|||
};
|
||||
|
||||
function populateChildren(menulist, options, selectedIndex, zoom,
|
||||
uaBackgroundColor, uaColor,
|
||||
uaBackgroundColor, uaColor, sheet,
|
||||
parentElement = null, isGroupDisabled = false,
|
||||
adjustedTextSize = -1, addSearch = true, nthChildIndex = 1) {
|
||||
let element = menulist.menupopup;
|
||||
let win = element.ownerGlobal;
|
||||
let scopedStyleSheet = menulist.querySelector("#ContentSelectDropdownScopedStylesheet");
|
||||
if (!scopedStyleSheet) {
|
||||
let doc = element.ownerDocument;
|
||||
scopedStyleSheet = doc.createElementNS("http://www.w3.org/1999/xhtml", "style");
|
||||
scopedStyleSheet.setAttribute("id", "ContentSelectDropdownScopedStylesheet");
|
||||
scopedStyleSheet.scoped = true;
|
||||
scopedStyleSheet.hidden = true;
|
||||
scopedStyleSheet = menulist.appendChild(scopedStyleSheet);
|
||||
}
|
||||
|
||||
// -1 just means we haven't calculated it yet. When we recurse through this function
|
||||
// we will pass in adjustedTextSize to save on recalculations.
|
||||
|
@ -228,7 +242,6 @@ function populateChildren(menulist, options, selectedIndex, zoom,
|
|||
}
|
||||
|
||||
if (ruleBody) {
|
||||
let sheet = scopedStyleSheet.sheet;
|
||||
sheet.insertRule(`${item.localName}:nth-child(${nthChildIndex}):not([_moz-menuactive="true"]) {
|
||||
${ruleBody}
|
||||
}`, 0);
|
||||
|
@ -250,7 +263,7 @@ function populateChildren(menulist, options, selectedIndex, zoom,
|
|||
if (isOptGroup) {
|
||||
nthChildIndex =
|
||||
populateChildren(menulist, option.children, selectedIndex, zoom,
|
||||
uaBackgroundColor, uaColor,
|
||||
uaBackgroundColor, uaColor, sheet,
|
||||
item, isDisabled, adjustedTextSize, false);
|
||||
} else {
|
||||
if (option.index == selectedIndex) {
|
||||
|
|
|
@ -135,6 +135,7 @@ menuitem[_moz-menuactive="true"] {
|
|||
background-color: Highlight;
|
||||
}
|
||||
|
||||
menupopup[customoptionstyling="true"],
|
||||
menuitem[customoptionstyling="true"] {
|
||||
-moz-appearance: none;
|
||||
padding-top: 0;
|
||||
|
|
Загрузка…
Ссылка в новой задаче