Bug 1427950 - Dispatch a "change" event from <rich-select> when a user changes the selectedness. r=jaws
Programmatic changes don't dispatch the event in order to avoid infinite loops.
MozReview-Commit-ID: 1GYFaSasAZO
--- a/toolkit/components/payments/res/components/rich-option.js
+++ b/toolkit/components/payments/res/components/rich-option.js
@@ -17,48 +17,14 @@ class RichOption extends ObservedPropert
"selected",
"value",
];
}
connectedCallback() {
this.classList.add("rich-option");
this.render();
- this.addEventListener("click", this);
- this.addEventListener("keydown", this);
}
render() {}
-
- handleEvent(event) {
- switch (event.type) {
- case "click": {
- this.onClick(event);
- break;
- }
- case "keydown": {
- this.onKeyDown(event);
- break;
- }
- }
- }
-
- onClick(event) {
- if (this.closest("rich-select").open &&
- !this.disabled &&
- event.button == 0) {
- for (let option of this.parentNode.children) {
- option.selected = option == this;
- }
- }
- }
-
- onKeyDown(event) {
- if (!this.disabled &&
- event.which == 13 /* Enter */) {
- for (let option of this.parentNode.children) {
- option.selected = option == this;
- }
- }
- }
}
customElements.define("rich-option", RichOption);
--- a/toolkit/components/payments/res/components/rich-select.js
+++ b/toolkit/components/payments/res/components/rich-select.js
@@ -96,45 +96,62 @@ class RichSelect extends ObservedPropert
onBlur(event) {
if (event.target == this) {
this.open = false;
}
}
onClick(event) {
- if (!this.disabled &&
- event.button == 0) {
- this.open = !this.open;
+ if (event.button != 0) {
+ return;
}
+
+ let option = event.target.closest(".rich-option");
+ if (this.open && option && !option.matches(".rich-select-selected-clone") && !option.selected) {
+ this.selectedOption = option;
+ this._dispatchChangeEvent();
+ }
+ this.open = !this.open;
}
onKeyDown(event) {
if (event.key == " ") {
this.open = !this.open;
} else if (event.key == "ArrowDown") {
let selectedOption = this.selectedOption;
let next = selectedOption.nextElementSibling;
if (next) {
next.selected = true;
selectedOption.selected = false;
+ this._dispatchChangeEvent();
}
} else if (event.key == "ArrowUp") {
let selectedOption = this.selectedOption;
let next = selectedOption.previousElementSibling;
if (next) {
next.selected = true;
selectedOption.selected = false;
+ this._dispatchChangeEvent();
}
} else if (event.key == "Enter" ||
event.key == "Escape") {
this.open = false;
}
}
+ /**
+ * Only dispatched upon a user-initiated change.
+ */
+ _dispatchChangeEvent() {
+ let changeEvent = document.createEvent("UIEvent");
+ changeEvent.initEvent("change", true, true);
+ this.dispatchEvent(changeEvent);
+ }
+
_optionsAreEquivalent(a, b) {
if (!a || !b) {
return false;
}
let aAttrs = a.constructor.observedAttributes;
let bAttrs = b.constructor.observedAttributes;
if (aAttrs.length != bAttrs.length) {