Skip to content

Instantly share code, notes, and snippets.

@motsu0
Last active November 8, 2023 08:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save motsu0/a208f55d3272d36c8cf390124d330324 to your computer and use it in GitHub Desktop.
Save motsu0/a208f55d3272d36c8cf390124d330324 to your computer and use it in GitHub Desktop.
[HTML] Create original SELECT with OPTION to include images.
@charset "utf-8";
.ImageSelector{
display: inline-flex;
position: relative;
box-sizing: border-box;
border: 1px solid #777;
background-color: #fff;
cursor: pointer;
}
.ImageSelector__display,.ImageSelector__preview,.ImageSelector__preview-child{
display: flex;
align-items: center;
}
.ImageSelector__preview,.ImageSelector__option{
padding: 4px;
}
.ImageSelector__option{
display: inline-flex;
background-color: #fff;
}
.ImageSelector__option:hover{
background-color: #3498DB;
color: #fff;
}
.ImageSelector__icon{
width: 20px;
position: relative;
}
.ImageSelector__icon::before,.ImageSelector__icon::after{
content: "";
width: 50%;
height: 4px;
position: absolute;
top: 55%;
background-color: #555;
}
.ImageSelector__icon::before{
left: 0;
transform-origin: bottom right;
transform: translate(0,-50%) rotate(45deg);
}
.ImageSelector__icon::after{
left: 50%;
transform-origin: bottom left;
transform: translate(0,-50%) rotate(-45deg);
}
.ImageSelector__pulldown{
display: none;
flex-direction: column;
box-sizing: border-box;
max-height: 300px;
position: absolute;
top: 100%;
left: -1px;
z-index: 10;
border: 1px solid #777;
background-color: #fff;
overflow-y: auto;
}
.ImageSelector__s-spread{
display: flex;
}
/*!
* image-selector.js v1.0
*
* Copyright (c) 2023 motsu
*
* Released under the MIT license.
* see https://opensource.org/licenses/MIT
*/
class ImageSelector{
#el_pulldown;
#els_option;
#el_preview;
#funcOnChange;
constructor(el_parent){
if(!el_parent instanceof HTMLElement) return undefined;
el_parent.classList.add('ImageSelector');
this.#els_option = el_parent.getElementsByClassName('ImageSelector__option');
if(this.#els_option.length<1) return undefined;
//プルダウン作成
this.#el_pulldown = document.createElement('div');
this.#el_pulldown.classList.add('ImageSelector__pulldown');
//選択中要素+アイコンスペース
const el_display = document.createElement('div');
el_display.classList.add('ImageSelector__display')
el_display.addEventListener('click',()=>{
this.#el_pulldown.classList.toggle('ImageSelector__s-spread');
})
el_parent.appendChild(el_display);
//選択中要素欄
this.#el_preview = document.createElement('div');
this.#el_preview.classList.add('ImageSelector__preview')
const els_selected = el_parent.getElementsByClassName('ImageSelector__s-selected');
if(els_selected.length===0) this.#els_option[0].classList.add('ImageSelector__s-selected');
const el_clone_option_first = (els_selected.length===0) ? this.#els_option[0].cloneNode(true) : els_selected[0].cloneNode(true);
el_clone_option_first.classList.add('ImageSelector__preview-child');
el_clone_option_first.classList.remove('ImageSelector__option');
el_clone_option_first.classList.remove('ImageSelector__s-selected');
this.value = el_clone_option_first.dataset.value;
this.#el_preview.appendChild(el_clone_option_first);
el_display.appendChild(this.#el_preview);
//プルダウン追加
el_parent.appendChild(this.#el_pulldown);
[...this.#els_option].forEach(el_option=>{
el_option.addEventListener('click',()=>{
this.#selectOption(el_option);
});
this.#el_pulldown.appendChild(el_option);
});
//セレクトアイコン追加
const el_icon = document.createElement('div');
el_icon.classList.add('ImageSelector__icon');
el_display.appendChild(el_icon);
//外部クリック処理
const css_celector = (el_parent.id==='') ? '.ImageSelector' : '#'+el_parent.id;
window.addEventListener('click',(e)=>{
if(e.target.closest(css_celector)===null) this.#el_pulldown.classList.remove('ImageSelector__s-spread');
});
//
}
#selectOption(el_option){
//s-selected処理
[...this.#els_option].forEach(el=>{
el.classList.remove('ImageSelector__s-selected');
});
el_option.classList.add('ImageSelector__s-selected');
//表示要素作成
const el_clone_option = el_option.cloneNode(true);
el_clone_option.classList.add('ImageSelector__preview-child');
el_clone_option.classList.remove('ImageSelector__option');
el_clone_option.classList.remove('ImageSelector__s-selected');
this.#el_preview.textContent = '';
this.#el_preview.appendChild(el_clone_option);
//
this.value = el_option.dataset.value;
this.#el_pulldown.classList.remove('ImageSelector__s-spread');
this.onChange();
}
setHeight(num){
if(Number.isInteger(num)&&num>0) this.#el_pulldown.style.maxHeight = num +'px';
}
setValue(val){
for(let i=0;i<this.#els_option.length;i++){
if(this.#els_option[i].dataset.value===val){
this.#selectOption(this.#els_option[i]);
break;
}
}
}
setOnChange(func){
this.#funcOnChange = func;
}
onChange(){
if(typeof this.#funcOnChange === 'function') this.#funcOnChange();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment