我有这个,比方说小测验,我在这里做问题。看起来是这样的:

用户可以选择以4种不同的方式显示此评级系统:
默认的评级系统是从1到5个数字。但用户可以选择从1到10,使用切换开关以及星星而不是数字。我的问题是,当开关打开时,我不知道如何再添加5个数字,然后当开关关闭时,再删除它们,或者在另一个开关打开时删除数字和添加星星。
我想我需要这样的东西:
depending on the current state:
if (1-10_switch.isChanged){
(addMore(stars || numbers) || remove )
}
else if (stars_switch.isChanged){
(changeIconTo(stars || numbers))
}我有代码来检查开关是否打开和关闭:
oneToTenButtonCheckbox.addEventListener("change", function () {
OneToTen = OneToTen ? false : true;
});
starsButtonCheckbox.addEventListener("change", function () {
isStars = isStars ? false : true;
});这是我加数字的代码:
var numbersDiv = document.createElement("div");
numbersDiv.className = "row";
for (let i = 0; i < 5; i++) {
var num = document.createElement("div");
num.insertAdjacentText("beforeend", i + 1);
if (i == 0) num.className = "col-1 offset-1 mb-2";
else num.className = "col-1 mb-2";
numbersDiv.appendChild(num);
}有人知道我能用什么方法解决这个问题吗?或者是有人做了这件事知道该怎么做?谢谢。
发布于 2022-07-29 12:02:52
这是我的完全动态和通用的解决方案。我想出了一个动态解决方案,因为我假设您需要创建多个测试,因此需要多个评分选择器。
我们可以使用HTMLDivElement.函数创建一个评级选择器元素,并返回一个createRatingSelector。
const stateElement = document.getElementById("state");
const quizRatingSelector = createRatingSelector({
altRatingScale: 10,
defaultRatingScale: 5,
altRatingType: "star",
defaultRatingType: "number",
altRatingTypeLabel: "Star",
defaultRatingTypeLabel: "Number Scale",
// listen to change event
onChange: ({ratingScale, ratingType}) => {
const stateString = `scale: ${ratingScale}, type: ${ratingType}`;
stateElement.innerText = stateString;
},
});
document.body.appendChild(quizRatingSelector);
// we can get the current state as
// console.log(quizRatingSelector.getState());
// ------------------------------------------
// returns a <div> element
// see the argument destructuring below to understand function API
function createRatingSelector(arg = {}) {
const {
altRatingType,
altRatingScale,
defaultRatingType,
altRatingTypeLabel,
defaultRatingScale,
// this function will be called whenever the rating scale or type changes
onChange = () => {},
defaultRatingTypeLabel,
NON_NUMBER_RATING_CHAR = "⭐",
parentClassName = "rating-selector",
typeSwitchClassName = "rating-type-switch",
scaleSwitchClassName = "rating-scale-switch",
outputElementClassName = "rating-selector-output",
} = arg;
const ratingSelector = document.createElement("div");
ratingSelector.setAttribute("class", parentClassName);
// we'll store the ratingType and ratingScale in the dataset of this selector
// in case you need it.
ratingSelector.dataset.ratingType = defaultRatingType;
ratingSelector.dataset.ratingScale = defaultRatingScale;
ratingSelector.getState = function () {
return {
ratingType: ratingSelector.dataset.ratingType,
ratingScale: ratingSelector.dataset.ratingScale,
};
};
const ratingOutput = document.createElement("div");
ratingOutput.setAttribute("class", outputElementClassName);
// this function is needed in the onClick function of switches
const showResultLocal = () =>
showResult({
outputElement: ratingOutput,
nonNumberValue: NON_NUMBER_RATING_CHAR,
ratingType: ratingSelector.dataset.ratingType,
ratingScale: ratingSelector.dataset.ratingScale,
});
const ratingScaleSwitch = createSwitch({
name: "rating-scale",
onValue: altRatingScale,
offValue: defaultRatingScale,
className: scaleSwitchClassName,
onLabel: `Rating Scale: 1 - ${altRatingScale}`,
offLabel: `Rating Scale: 1 - ${defaultRatingScale}`,
onClick: ({ value }) => {
ratingScale = value;
ratingSelector.dataset.ratingScale = value;
showResultLocal();
onChange(ratingSelector.getState());
},
});
const ratingTypeSwitch = createSwitch({
name: "rating-type",
className: typeSwitchClassName,
onValue: altRatingType,
offValue: defaultRatingType,
onLabel: `Rating type: ${altRatingTypeLabel}`,
offLabel: `Rating type: ${defaultRatingTypeLabel}`,
onClick: ({ value }) => {
ratingSelector.dataset.ratingType = value;
showResultLocal();
onChange(ratingSelector.getState());
},
});
ratingSelector.appendChild(ratingScaleSwitch);
ratingSelector.appendChild(ratingTypeSwitch);
ratingSelector.appendChild(ratingOutput);
showResultLocal();
return ratingSelector;
}
/**
* Creates a __input__ and __label__ element and wraps it with a <div>
* e.g.,
* <div>
* <label>The Label</label>
* <input type="checkbox" ...other attributes... />
* </div>
*
* see the argument destructuring below to understand function API
* */
function createSwitch(arg = {}) {
const {
onLabel,
offLabel,
onValue,
offValue,
id = "",
name = "",
className = "",
onClick = () => {},
} = arg;
const switchName = name;
const switchAttributes = {
id,
name: switchName,
class: className,
type: "checkbox",
};
const toggleSwitch = document.createElement("input");
for (const [name, value] of Object.entries(switchAttributes))
toggleSwitch.setAttribute(name, value);
const switchLabel = document.createElement("label");
switchLabel.setAttribute("for", switchName);
switchLabel.innerText = offLabel;
// click event handling
toggleSwitch.addEventListener("click", () => {
switchLabel.innerText = toggleSwitch.checked ? onLabel : offLabel;
onClick({
id,
name: switchName,
active: toggleSwitch.checked,
value: toggleSwitch.checked ? onValue : offValue,
});
});
const switchWrapper = document.createElement("div");
switchWrapper.appendChild(toggleSwitch);
switchWrapper.appendChild(switchLabel);
return switchWrapper;
}
// see the argument destructuring below to understand function API
function showResult(arg = {}) {
const { outputElement, ratingScale, ratingType, nonNumberValue } = arg;
while (outputElement.childNodes.length > ratingScale)
outputElement.removeChild(outputElement.childNodes[0]);
while (outputElement.childNodes.length < ratingScale)
outputElement.appendChild(document.createElement("span"));
outputElement.childNodes.forEach((child, index) => {
child.innerText = ratingType === "number" ? index + 1 : nonNumberValue;
});
}.rating-selector-output > span {
width: 2ch;
text-align: center;
display: inline-block;
}<body>
<p id="state">State...</p>
<hr>
</body>
如果你有任何问题,请随便问我。希望这能有所帮助。
https://stackoverflow.com/questions/73163500
复制相似问题