/**
* @summary Selectron23
* @description drop-down
* @version 1.0.3
* @file selectron23
* @author realmag777
* @contact https://pluginus.net/contact-us/
* @github https://github.com/realmag777/selectron23
* @copyright Copyright 2021 Rostislav Sofronov
*
* This source file is free software, available under the following license:
* MIT license - https://en.wikipedia.org/wiki/MIT_License .Basically that
* means you are free to use Selectron23 as long as this header is left intact.
*/
'use strict';
class Selectron23 {
constructor(element, data = {}) {
this.data = data;
this.scale = 1;
Selectron23.z_index = 9999;
this.el = document.createElement('div');
this.el.className = 'selectron23';
this.element = element;
if (this.element.tagName.toLowerCase() === 'select') {
this.element.insertAdjacentElement('afterend', this.el);
} else {
this.element.insertAdjacentElement('afterbegin', this.el);
}
if (this.element.tagName.toLowerCase() === 'select') {
//select replacement
this.element.style.display = 'none';
if (this.element.hasAttribute('style')) {
if (this.element.style.width) {
this.data.width = this.element.style.width;
}
}
let selected = null;
let options = this.element.querySelectorAll('option');
if (options.length > 0) {
let fusion = Boolean(this.data.fusion);
let opt = [];
options.forEach((o) => {
let d = {
value: o.value,
title: o.textContent
};
if (o.hasAttribute('data-img') && o.getAttribute('data-img').length > 0) {
d.img = o.getAttribute('data-img');
}
if (o.hasAttribute('data-text') && o.getAttribute('data-text').length > 0) {
d.text = o.getAttribute('data-text');
}
opt.push(d);
if (o.hasAttribute('selected')) {
selected = o.value;
}
});
//data fusion
if (fusion) {
this.data.options.forEach((o) => {
opt = opt.map((op) => {
if (op.value.toString() === o.value.toString()) {
op = o;
}
return op;
});
});
}
//+++
this.data.options = opt;
if (selected !== null) {
this.data.selected = selected;
}
}
//+++
if (Object.keys(this.element.dataset).length > 0) {
Object.keys(this.element.dataset).forEach((key) => {
this.data[key] = this.element.dataset[key];
});
}
}
//+++
this.container = null;
this.value = null;
this.input = null;
this._draw();
this.el.querySelector('*').addEventListener('click', ev => this._click(ev));
document.addEventListener('click', ev => this.show(false));
document.addEventListener('set_selectron23_value', ev => {
let can = false;
if (ev.detail.selects === 'all') {
can = true;
}
if (can) {
this.select(ev.detail.value, false);
}
});
return this;
}
_draw() {
if (this.data.options.length > 0) {
this.container = document.createElement('div');
this.container.className = 'selectron23-container';
this.el.appendChild(this.container);
this.container.setAttribute('data-opened', 0);
this.data.options.forEach((o) => {
this.append(o);
});
this.pointer = document.createElement('span');
this.pointer.setAttribute('data-pointer', 1);
this.container.appendChild(this.pointer);
}
if (typeof this.data.selected !== 'undefined') {
this.select(this.data.selected);
} else {
if (typeof this.data.label !== 'undefined' && this.data.label.length > 0) {
let option = document.createElement('div');
option.setAttribute('data-label', 1);
option.className = 'selectron23-option';
option.innerHTML = `
${this.data.label}
`;
this.container.insertAdjacentElement('afterbegin', option);
} else {
this.container.querySelector('div').setAttribute('data-selected', 1);
}
}
if (typeof this.data.width !== 'undefined') {
//this.container.style.width = this.data.width;
this.el.style.flexBasis = this.el.style.width = this.data.width;
}
if (typeof this.data.name !== 'undefined') {
this.input = document.createElement('input');
this.input.setAttribute('type', 'hidden');
this.input.setAttribute('name', this.data.name);
this.input.setAttribute('value', '');
if (this.container.querySelector('div').hasAttribute('data-value')) {
this.input.setAttribute('value', this.container.querySelector('div').getAttribute('data-value'));
}
this.el.appendChild(this.input);
}
this._normalize_min_height();
}
append(data) {
if (!this.container.querySelector(`[data-value="${data.value}"]`)) {
let option = this._create_option(data);
this.container.appendChild(option);
return true;
}
return false;
}
_create_option(data) {
let option = document.createElement('div');
option.setAttribute('data-value', data.value);
option.className = 'selectron23-option';
let float = 'left';
if (typeof this.data.imgpos !== 'undefined') {
if (this.data.imgpos === 'right') {
float = 'right';
}
}
let title = '';
if (data.title) {
title = `${data.title}
`;
}
let text = '';
if (data.text) {
text = `${data.text}
`;
}
let img = '';
if (data.img) {
let margin_top = 0;
if (!text) {
margin_top = 'margin-top: -6px;';
}
img = `
`;
}
option.innerHTML = `${img}${title}${text}
`;
if (typeof data.title_attributes !== 'undefined' && Object.keys(data.title_attributes).length > 0) {
for (const [kk, vv] of Object.entries(data.title_attributes)) {
option.querySelector('.selectron23-option-title').setAttribute(kk, vv);
}
}
if (img) {
//option.querySelector('img').style.maxHeight = parseInt(option.offsetHeight - option.offsetHeight * 0.25) + 'px';
option.querySelector('img').style.maxHeight = '38px';
}
return option;
}
select(value, call_event = true) {
if (this.value !== value) {
if (!this.container.querySelector(`[data-value="${value}"]`)) {
return;
}
this.value = value;
this._remove_label();
let option = this.container.querySelector(`[data-value="${value}"]`);
option.setAttribute('data-selected', 1);
this.container.insertAdjacentElement('afterbegin', option);
this.data.options.reverse().forEach((o) => {
if (o.value !== value) {
let opt = this.container.querySelector(`[data-value="${o.value}"]`);
option.insertAdjacentElement('afterend', opt);
opt.removeAttribute('data-selected');
}
});
this._normalize_min_height();
if (this.input) {
this.input.value = value;
}
if (call_event) {
this.onSelect();
}
return true;
}
return false;
}
_remove_label() {
if (this.container.querySelector(`[data-label="1"]`)) {
this.container.querySelector(`[data-label="1"]`).remove();
}
}
_click(ev) {
let target = ev.target;
if (!target.hasAttribute('data-value') && !target.hasAttribute('data-pointer')) {
target = target.closest('.selectron23-option');
}
if (!target) {
this.show(false);
return;
}
if (target.hasAttribute('data-pointer') || target.hasAttribute('data-label')
|| target.hasAttribute('data-selected')) {
if (parseInt(this.container.getAttribute('data-opened')) === 1) {
this.show(false);
} else {
this.show(true);
}
} else {
this.select(target.getAttribute('data-value'));
this.show(false);
if (this.element.tagName.toLowerCase() === 'select') {
this.element.value = this.value;
this.element.dispatchEvent(new Event("change"));
}
}
}
show(is, dir = 'down') {
if (is) {
if (parseInt(this.container.getAttribute('data-opened'))) {
return;
}
this.container.style.zIndex = ++Selectron23.z_index;//to avoid css issue with anothers selectron23 drop-downs
//animation
let counter = 1;
let timer = setInterval(() => {
let max_height = 0;
if (typeof this.data.max_open_height !== 'undefined' && this.data.max_open_height > 0) {
max_height = parseInt(this.data.max_open_height);
} else {
this.container.querySelectorAll('.selectron23-option').forEach(function (item) {
max_height += item.offsetHeight;
});
}
//growing
this.container.style.maxHeight = parseFloat(0.05 * counter) * max_height + 'px';
if (parseInt(this.container.style.maxHeight) >= max_height) {
clearInterval(timer);
if (typeof this.data.max_open_height !== 'undefined') {
this.container.style.maxHeight = max_height + 'px';
this.container.style.overflow = 'auto';
} else {
this.container.style.maxHeight = '100vh';
}
this.container.setAttribute('data-opened', 1);
this.pointer.style.top = (parseInt(this.pointer.style.top) + 1) + 'px';
}
counter++;
}, 10);
} else {
if (!parseInt(this.container.getAttribute('data-opened'))) {
return;
}
this.container.setAttribute('data-opened', 0);
this.pointer.style.top = (parseInt(this.pointer.style.top) - 1) + 'px';
this._normalize_min_height();
this.container.style.maxHeight = this.container.style.minHeight;
if (typeof this.container.style.overflow !== 'undefined') {
this.container.scrollTop = 0;//!!
this.container.style.overflow = null;
}
}
}
_normalize_min_height() {
let curr_height = this.container.querySelector('div').clientHeight;
if (curr_height == 0) {
curr_height = 35;
}
this.container.style.minHeight = curr_height + 'px';
this.el.style.height = (parseInt(this.container.style.minHeight) + 1) + 'px';//!!
this.pointer.style.top = (parseInt(this.container.style.minHeight) / 2) - 2 + 'px';
//this.el.style.maxHeight = window.getComputedStyle(this.el, null).getPropertyValue('min-height');
}
setWidth(width) {
if (width === '100p') {
this.el.style.flexBasis = this.el.style.width = this.element.style.width = '100%';
} else {
this.el.style.flexBasis = this.el.style.width = this.element.style.width = width + 'px';
}
}
setScale(height) {
let scale = parseFloat(height / 100);
this.el.style.transform = `scale(${scale})`;
}
setDescriptionTextSize(size) {
this.el.querySelectorAll('.selectron23-option-text').forEach((option) => {
option.style.fontSize = size + 'px';
});
this._normalize_min_height();
}
setTitleFontSize(size) {
this.el.querySelectorAll('.selectron23-option-title').forEach((option) => {
option.style.fontSize = size + 'px';
});
this._normalize_min_height();
}
setTitleValue(value) {
this.el.querySelectorAll('.selectron23-option-title').forEach((option) => {
if (value.length > 0) {
option.innerText = value;
}
});
}
setTitleFont(font) {
this.el.querySelectorAll('.selectron23-option-title').forEach((option) => {
option.style.fontFamily = font;
});
this._normalize_min_height();
}
setDescriptionFont(font) {
this.el.querySelectorAll('.selectron23-option-text').forEach((option) => {
option.style.fontFamily = font;
});
this._normalize_min_height();
}
setBorderRadius(radius) {
let scale = parseFloat(radius / 100);
this.container.style.borderRadius = (parseInt(this.container.style.minHeight) / 2 * scale) + 'px';
}
showImg(is) {
this.el.querySelectorAll('.selectron23-img').forEach((option) => {
option.style.display = is ? 'inline-block' : 'none';
});
this._normalize_min_height();
}
setImgVPosition(margin) {
this.el.querySelectorAll('.selectron23-img').forEach((option) => {
option.style.marginTop = margin + 'px';
});
this._normalize_min_height();
}
setImgHeight(height) {
this.el.querySelectorAll('.selectron23-img').forEach((option) => {
option.style.height = height + 'px';
option.style.maxHeight = height + 'px';
});
this._normalize_min_height();
}
setImgSide(side) {
this.el.querySelectorAll('.selectron23-img').forEach((option) => {
option.style.float = side ? 'right' : 'left';
});
}
showDescription(is) {
this.el.querySelectorAll('.selectron23-option-text').forEach((option) => {
if (is) {
option.style.display = 'block';
} else {
option.style.display = 'none';
}
});
this._normalize_min_height();
}
showTitle(is) {
this.el.querySelectorAll('.selectron23-option-title').forEach((option) => {
if (is) {
option.style.display = 'block';
} else {
option.style.display = 'none';
}
});
this._normalize_min_height();
}
setBorderColor(value) {
this.container.style.borderColor = value;
}
setDescriptionColor(value) {
this.el.querySelectorAll('.selectron23-option-text').forEach((option) => {
option.style.color = value;
});
}
setTitleColor(value) {
this.el.querySelectorAll('.selectron23-option-title').forEach((option) => {
option.style.color = value;
});
}
setTitleBold(value) {
this.el.querySelectorAll('.selectron23-option-title').forEach((option) => {
option.style.fontWeight = value ? 'bold' : 'normal';
});
this._normalize_min_height();
}
setBackgroundColor(value) {
this.el.querySelectorAll('.selectron23-option').forEach((option) => {
option.style.background = value;
});
}
setPointerColor(value) {
//this.pointer.style.borderColor = value;
this.pointer.style.color = value;
}
setContainerBgColor(value) {
this.container.style.background = value;
}
setDividerSize(value) {
this.el.querySelectorAll('.selectron23-option').forEach((option) => {
option.style.marginBottom = value + 'px';
});
this._normalize_min_height();
}
setBorderWidth(value) {
this.container.style.borderWidth = value + 'px';
}
setMaxOpenHeight(value) {
this.data.max_open_height = value;
this._normalize_min_height();
}
applyDesignSettings(settings) {
for (const [key, value] of Object.entries(settings)) {
switch (key) {
case 'width':
this.setWidth(value);
if (settings.width_p100) {
this.setWidth('100p');
}
break;
case 'img_pos':
this.setImgSide(value);
break;
case 'max_open_height':
this.setMaxOpenHeight(value);
break;
case 'show_img':
this.showImg(value);
break;
case 'scale':
this.setScale(value);
break;
case 'description_font_size':
this.setDescriptionTextSize(value);
break;
case 'title_show':
this.showTitle(value);
break;
case 'title_font_size':
this.setTitleFontSize(value);
break;
case 'title_color':
this.setTitleColor(value);
break;
case 'title_bold':
this.setTitleBold(value);
break;
case 'title_font':
this.setTitleFont(value);
break;
case 'title_value':
this.setTitleValue(value);
break;
case 'border_radius':
this.setBorderRadius(value);
break;
case 'border_color':
this.setBorderColor(value);
break;
case 'img_height':
this.setImgHeight(value);
break;
case 'img_vertival_pos':
this.setImgVPosition(value);
break;
case 'show_description':
this.showDescription(value);
break;
case 'description_color':
this.setDescriptionColor(value);
break;
case 'description_font':
this.setDescriptionFont(value);
break;
case 'background_color':
this.setBackgroundColor(value);
break;
case 'pointer_color':
this.setPointerColor(value);
break;
case 'divider_color':
this.setContainerBgColor(value);
break;
case 'divider_size':
this.setDividerSize(value);
break;
case 'border_width':
this.setBorderWidth(value);
break;
}
}
this._normalize_min_height();
}
onSelect() {
//for API
}
}