Custom element, Shadow DOM で作るセレクト

Shadow DOM

Shadow DOM

Custom element, Shadow DOM で作るセレクト

複数選択機能をShadow DOMで封じ込め

ライオン,チータ,ペガサス,ゾウ,猿,狼,子守熊,虎,黒ひょう,ひつじ,たぬき,こじか,9
却下!,採用します,0
A,B,O,AB,unknown,4
記述コード:
選択肢1,2...,初期値 を挟みます。レスポンシブ対応

<ce-select>ライオン,チータ,ペガサス,ゾウ,猿,狼,子守熊,虎,黒ひょう,ひつじ,たぬき,こじか,9</ce-select>
<ce-select>却下!,採用します,0</ce-select>
<ce-select>A,B,O,AB,unknown,4</ce-select>

<script defer src="./js/ce_select.js"></script>
		
現時点のコードは以下の通り:
/**
 * セレクト
 *
 * 選択肢1,2...,初期値
 * <ce-select>ライオン,チータ,ペガサス,ゾウ,猿,狼,子守熊,虎,黒ひょう,ひつじ,たぬき,こじか,10</ce-select>
 * <ce-toggleselect>NO,YES,0</ce-toggleselect>
 * <ce-select>A,B,O,AB,unknown,4</ce-select>
 *
 * @author ao-system, Inc.
 * @date 2024-06-15
 */
(() => {
	'use strict';
	class CustomElementSelect {
		#style = `
			:host > div {
				--color-base: #fff;
				--color-off: #777;
				--color-on: #fff;
				--color-checked: #3c0;
				--transition-time: 300ms;
				user-select: none;
				padding: 3px;
				background-color: var(--color-base);
				border-radius: 20px;
				display: grid;
				&[alt="0"] > div:nth-of-type(2) > label:nth-of-type(1) {	color: var(--color-on);	}
				&[alt="1"] > div:nth-of-type(2) > label:nth-of-type(2) {	color: var(--color-on);	}
				&[alt="2"] > div:nth-of-type(2) > label:nth-of-type(3) {	color: var(--color-on);	}
				&[alt="3"] > div:nth-of-type(2) > label:nth-of-type(4) {	color: var(--color-on);	}
				&[alt="4"] > div:nth-of-type(2) > label:nth-of-type(5) {	color: var(--color-on);	}
				&[alt="5"] > div:nth-of-type(2) > label:nth-of-type(6) {	color: var(--color-on);	}
				&[alt="6"] > div:nth-of-type(2) > label:nth-of-type(7) {	color: var(--color-on);	}
				&[alt="7"] > div:nth-of-type(2) > label:nth-of-type(8) {	color: var(--color-on);	}
				&[alt="8"] > div:nth-of-type(2) > label:nth-of-type(9) {	color: var(--color-on);	}
				&[alt="9"] > div:nth-of-type(2) > label:nth-of-type(10) {	color: var(--color-on);	}
				&[alt="10"] > div:nth-of-type(2) > label:nth-of-type(11) {	color: var(--color-on);	}
				&[alt="11"] > div:nth-of-type(2) > label:nth-of-type(12) {	color: var(--color-on);	}
				&[alt="12"] > div:nth-of-type(2) > label:nth-of-type(13) {	color: var(--color-on);	}
				&[alt="13"] > div:nth-of-type(2) > label:nth-of-type(14) {	color: var(--color-on);	}
				&[alt="14"] > div:nth-of-type(2) > label:nth-of-type(15) {	color: var(--color-on);	}
				container-type: inline-size;
				> div {
					grid-area: 1/1/2/2;
					&:nth-of-type(1) {
						border-radius: 20px;
						background-color: var(--color-checked);
						transition: margin var(--transition-time);
					}
					&:nth-of-type(2) {
						display: grid;
						> label {
							cursor: pointer;
							font-size: 15px;
							line-height: 1;
							font-weight: 600;
							padding: 12px 1px;
							text-align: center;
							transition: color var(--transition-time);
							color: var(--color-off);
							@container (width < 1050px) {
								writing-mode: vertical-rl;
								text-orientation: upright;
								padding-block: calc(50% - 0.5em);
							}
						}
					}
				}
			}
		`;
		constructor() {
		}
		render(elm) {
			const styleElm = document.createElement('style');
			styleElm.innerHTML = this.#style;
			//
			const ary = elm.innerText.split(',');
			const itemCount = ary.length - 1;
			const initial = ary[ary.length - 1];
			//
			const divElm = document.createElement('div');
			const div1 = document.createElement('div');
			div1.style.width = String(1 / itemCount * 100) + '%';
			divElm.appendChild(div1);
			const div2 = document.createElement('div');
			for (let i = 0; i < itemCount; i++) {
				const label = document.createElement('label');
				label.textContent = ary[i];
				label.addEventListener('click',() => {
					divElm.setAttribute('alt',i);
					div1.style.marginLeft = String(1 / itemCount * 100 * i) + '%';
				});
				div2.appendChild(label);
			}
			div2.style.gridTemplateColumns = 'repeat(' + itemCount + ',1fr)';
			divElm.appendChild(div2);
			divElm.setAttribute('alt',initial);
			div1.style.marginLeft = String(1 / itemCount * 100 * initial) + '%';
			//
			const shadowRoot = elm.attachShadow({mode:'closed'});
			shadowRoot.appendChild(styleElm);
			shadowRoot.appendChild(divElm);
		}
	}
	(() => {
		const customElementSelect = new CustomElementSelect();
		customElements.define('ce-select',
			class extends HTMLElement {
				constructor() {
					super();
					customElementSelect.render(this);
				}
			}
		);
	})();
})();
この記事は2024年6月当時の物です。
このサイトについてのお問い合わせはエーオーシステムまでお願いいたします。
ご使用上の過失の有無を問わず、本プログラムの運用において発生した損害に対するいかなる請求があったとしても、その責任を負うものではありません。