/* 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/. */
import BasicCardOption from "../components/basic-card-option.js";
import PaymentStateSubscriberMixin from "../mixins/PaymentStateSubscriberMixin.js";
import RichSelect from "../components/rich-select.js";
import paymentRequest from "../paymentRequest.js";
/**
*
* Container around add/edit links and with
* listening to savedBasicCards.
*/
export default class PaymentMethodPicker extends PaymentStateSubscriberMixin(HTMLElement) {
constructor() {
super();
this.dropdown = new RichSelect();
this.dropdown.addEventListener("change", this);
this.spacerText = document.createTextNode(" ");
this.securityCodeInput = document.createElement("input");
this.securityCodeInput.autocomplete = "off";
this.securityCodeInput.size = 3;
this.securityCodeInput.addEventListener("change", this);
this.addLink = document.createElement("a");
this.addLink.href = "javascript:void(0)";
this.addLink.textContent = this.dataset.addLinkLabel;
this.addLink.addEventListener("click", this);
this.editLink = document.createElement("a");
this.editLink.href = "javascript:void(0)";
this.editLink.textContent = this.dataset.editLinkLabel;
this.editLink.addEventListener("click", this);
}
connectedCallback() {
this.appendChild(this.dropdown);
this.appendChild(this.spacerText);
this.appendChild(this.securityCodeInput);
this.appendChild(this.addLink);
this.append(" ");
this.appendChild(this.editLink);
super.connectedCallback();
}
render(state) {
let basicCards = paymentRequest.getBasicCards(state);
let desiredOptions = [];
for (let [guid, basicCard] of Object.entries(basicCards)) {
let optionEl = this.dropdown.getOptionByValue(guid);
if (!optionEl) {
optionEl = new BasicCardOption();
optionEl.value = guid;
}
for (let key of BasicCardOption.recordAttributes) {
let val = basicCard[key];
if (val) {
optionEl.setAttribute(key, val);
} else {
optionEl.removeAttribute(key);
}
}
desiredOptions.push(optionEl);
}
let el = null;
while ((el = this.dropdown.popupBox.querySelector(":scope > basic-card-option"))) {
el.remove();
}
for (let option of desiredOptions) {
this.dropdown.popupBox.appendChild(option);
}
// Update selectedness after the options are updated
let selectedPaymentCardGUID = state[this.selectedStateKey];
let optionWithGUID = this.dropdown.getOptionByValue(selectedPaymentCardGUID);
this.dropdown.selectedOption = optionWithGUID;
if (selectedPaymentCardGUID && !optionWithGUID) {
throw new Error(`${this.selectedStateKey} option ${selectedPaymentCardGUID}` +
`does not exist in options`);
}
}
get selectedStateKey() {
return this.getAttribute("selected-state-key");
}
handleEvent(event) {
switch (event.type) {
case "change": {
this.onChange(event);
break;
}
case "click": {
this.onClick(event);
break;
}
}
}
onChange({target}) {
let selectedKey = this.selectedStateKey;
let stateChange = {};
if (!selectedKey) {
return;
}
switch (target) {
case this.dropdown: {
stateChange[selectedKey] = target.selectedOption && target.selectedOption.guid;
// Select the security code text since the user is likely to edit it next.
// We don't want to do this if the user simply blurs the dropdown.
this.securityCodeInput.select();
break;
}
case this.securityCodeInput: {
stateChange[selectedKey + "SecurityCode"] = this.securityCodeInput.value;
break;
}
default: {
return;
}
}
this.requestStore.setState(stateChange);
}
onClick({target}) {
let nextState = {
page: {
id: "basic-card-page",
},
};
switch (target) {
case this.addLink: {
nextState.page.guid = null;
break;
}
case this.editLink: {
let state = this.requestStore.getState();
let selectedPaymentCardGUID = state[this.selectedStateKey];
nextState.page.guid = selectedPaymentCardGUID;
break;
}
default: {
throw new Error("Unexpected onClick");
}
}
this.requestStore.setState(nextState);
}
}
customElements.define("payment-method-picker", PaymentMethodPicker);