const stateElement = document.getElementById("state");
const quizRatingSelector = createRatingSelector({
altRatingScale: 10,
defaultRatingScale: 5,
altRatingType: "star",
defaultRatingType: "number",
altRatingTypeLabel: "Star",
defaultRatingTypeLabel: "Number Scale",
onChange: ({ratingScale, ratingType}) => {
const stateString = `scale: ${ratingScale}, type: ${ratingType}`;
stateElement.innerText = stateString;
},
});
document.body.appendChild(quizRatingSelector);
function createRatingSelector(arg = {}) {
const {
altRatingType,
altRatingScale,
defaultRatingType,
altRatingTypeLabel,
defaultRatingScale,
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);
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);
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;
}
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;
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;
}
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>
1-10
的值时,它应该自动触发Stars
的切换。这种UI方式非常令人困惑,而实际上可以是相同的UI控件具有两个选项。显示/隐藏1-10 / 1-5的逻辑就像有两个HTML块,您只需切换可见/隐藏即可。创建和删除只是浪费时间和复杂性。而且它得到了4个赞..有时候这对我来说是个谜。 - Diego D