DOM toggleAttribute Demo
An interactive walkthrough of the quiet DOM API that adds, removes, forces, and reports element attributes with one method.
1. The Attribute API Family
Code:const panel = document.querySelector('#quiet-panel');
const quietOutput = document.querySelector('#quiet-output');
function quietSetDemoAttribute() {
panel.setAttribute('data-demo', 'on');
quietUpdate('setAttribute("data-demo", "on")');
}
function quietGetDemoAttribute() {
quietUpdate(`getAttribute("data-demo") -> ${panel.getAttribute('data-demo')}`);
}
function quietHasDemoAttribute() {
quietUpdate(`hasAttribute("data-demo") -> ${panel.hasAttribute('data-demo')}`);
}
function quietRemoveDemoAttribute() {
panel.removeAttribute('data-demo');
quietUpdate('removeAttribute("data-demo")');
}
function quietToggleDemoAttribute() {
const state = panel.toggleAttribute('data-demo');
quietUpdate(`toggleAttribute("data-demo") -> ${state}`);
}
function quietUpdate(action) {
quietOutput.textContent = `${action}\nCurrent markup: ${quietMarkup()}`;
}
function quietMarkup() {
const value = panel.getAttribute('data-demo');
const attribute = value === null
? ''
: value === ''
? ' data-demo'
: ` data-demo="${value}"`;
return `<div id="quiet-panel"${attribute}>Attribute target</div>`;
}
Result:
Attribute target
2. Boolean Attributes with force
Code:const dialog = document.querySelector('#boolean-dialog');
const booleanState = document.querySelector('#boolean-state');
function dialogOpen() {
dialog.toggleAttribute('open', true);
updateDialogState();
}
function dialogClose() {
dialog.toggleAttribute('open', false);
updateDialogState();
}
function dialogToggle() {
dialog.toggleAttribute('open');
updateDialogState();
}
function updateDialogState() {
booleanState.textContent = dialog.hasAttribute('open')
? '<dialog open>'
: '<dialog>';
}
Result:
Closed dialogs leave this space quiet.
disabled
readonly
checked
open
required
selected
3. Custom Attribute Names and Return Value
Code:const syntaxPreview = document.querySelector('#syntax-preview');
function toggleBodyAttribute() {
const isHasAttribute = document.body.toggleAttribute('zhangxinxu');
syntaxPreview.textContent = isHasAttribute
? '<body zhangxinxu>'
: '<body>';
}
Result:
The page reacts when the custom body attribute exists.
<body>
4. Disable an Input and Change Button Text with CSS
Code:<input id="input"> <button id="button" value="Enable">Disable</button>
#button {
position: relative;
min-width: 6.5rem;
}
#input:disabled ~ #button {
-webkit-text-fill-color: transparent;
}
#input:disabled ~ #button::before {
position: absolute;
content: attr(value);
-webkit-text-fill-color: currentColor;
inset: 0;
display: grid;
place-items: center;
}
button.addEventListener('click', _ => {
input.toggleAttribute('disabled');
});
Result:
Click the button to toggle the input's disabled attribute. The button text swap is controlled by the CSS selector above.
5. Tiny Polyfill Before Business Logic
Code:if (!Element.prototype.toggleAttribute) {
Element.prototype.toggleAttribute = function(name, force) {
if(force !== void 0) force = !!force
if (this.hasAttribute(name)) {
if (force) return true;
this.removeAttribute(name);
return false;
}
if (force === false) return false;
this.setAttribute(name, "");
return true;
};
}
const polyfillInput = document.querySelector('#polyfill-input');
const polyfillOutput = document.querySelector('#polyfill-output');
function toggleReadonlyWithPolyfill() {
const isReadonly = polyfillInput.toggleAttribute('readonly');
polyfillOutput.textContent = isReadonly
? 'readonly attribute is present'
: 'readonly attribute is absent';
}
Result:
The guarded polyfill runs first, then this input uses
toggleAttribute('readonly').readonly attribute is absent