$(document).ready(function () {
CustomSelectInitializer.init();
});
class CustomSelectOptionModel {
public id: string;
public value: string;
}
class CustomSelectInitializer {
public static init() {
$(".custom-select select").each((index, item) => {
CustomSelectInitializer.InitCustomSelect(item, false);
});
}
public static InitCustomSelect($select: HTMLElement, refresh: boolean) {
// Cache the number of options
let $this = $($select);
//Защита от повторной инициализации
if (!refresh && $this.parent().find(".styledSelect").length > 0) {
return;
}
//Простановка значения дополнительно, если есть касмтомный список
let selectedVal = $this.attr("selected-val");
if (selectedVal) {
let select = $((Array as any).from(($this[0] as any).options).filter(x => x.value === selectedVal.toUpperCase())[0]);
select.attr('selected', 'selected');
select.prop('selected', 'selected');
}
// Cache the styled div
var $styledSelect = $this.next('div.styledSelect');
var $list = $styledSelect.next('.options');
if (!refresh) {
// Hides the select element
$this.addClass('s-hidden');
// Wrap the select element in a div
$this.wrap('
');
// Insert a styled div to sit over the top of the hidden select element
$this.after('');
// Cache the styled div
$styledSelect = $this.next('div.styledSelect');
// Insert an unordered list after the styled div and also cache the list
$list = $('', {
'class': 'options'
}).insertAfter($styledSelect);
// Show the first select option in the styled div
var placeholder = $this.attr("placeholder");
if (placeholder) {
$styledSelect.attr('data-text', placeholder);
} else {
$styledSelect.html($this.find('option').eq(0).text());
}
}
else {
$styledSelect.empty();
$list.empty();
}
let items = $this.find('option, optgroup');
// Insert a list item into the unordered list for each select option
for (var i = 0; i < items.length; i++) {
var item = $(items.eq(i));
var hasGroups = $this.find('optgroup').length;
if (item.is("option")) {
var src = items.eq(i);
var newItem = $('',
{
html: src.text(),
rel: src.val(),
class: hasGroups ? "groupItem" : ""
});
CustomSelectInitializer.copyAttributes(src, newItem);
newItem.appendTo($list);
} else {
$('', {
text: items.eq(i).attr("label"),
class: "groupParent"
}).appendTo($list);
}
}
let $label = $this.closest(".custom-select").find("label");
if ($this.attr("disabled") != "disabled") {
// Show the unordered list when the styled div is clicked (also hides it if the div is clicked again)
$styledSelect.click(function (e) {
if ($(e.currentTarget).siblings('.select-input').prop('disabled'))
return;
var options = $(e.currentTarget).parent().find('.options');
if (options && options.length > 0 && options.css('display') == 'block') {
e.stopPropagation();
$(e.currentTarget).parent('.select').next('label.input-icon').toggleClass('active');
options.hide();
}
else {
CustomSelectInitializer.openDropDownList(e, this);
}
});
$label.click(function (e) {
if ($(e.currentTarget).siblings('div.select').find('.select-input').prop('disabled'))
return;
var options = $(e.currentTarget).parent().find('.options');
if (options && options.length > 0 && options.css('display') == 'block') {
e.stopPropagation();
$(e.currentTarget).parent().find('label.input-icon').toggleClass('active');
options.hide();
}
else {
var div = $(this).closest(".custom-select").find(".styledSelect")[0];
CustomSelectInitializer.openDropDownListLabel(e, div, $select);
}
});
}
CustomSelectInitializer.InitCustomOptions($select);
// Скрытие селекта при клике вне его.
// при клике на элемент группировки - не закрывать его
$(document).click(function (e) {
if (e.target instanceof HTMLElement) {
if (e.target == $select || $(e.target).hasClass("groupParent")) {
return;
}
}
$styledSelect.removeClass('active');
$($styledSelect).parent('.select').next('label.input-icon').removeClass('active');
$list.hide();
});
// простановка значений, если есть:
CustomSelectInitializer.SetSelectedValue($select);
$($select).on("set-selected", function () {
CustomSelectInitializer.SetSelectedValue(this);
});
$($select).trigger("custom-select-initialized", [$select]);
}
private static SetSelectedValue(element: HTMLElement) {
var placeholder = $(element).attr("placeholder");
if (placeholder && !$(element).attr("selected-val")) {
return;
}
var selectedVal = $(element).val() as string;
var chosenContainer = $(element).next(".styledSelect");
chosenContainer.parent().find("li[rel='" + selectedVal + "']").addClass("selected");
var option = $(element).find("option[value='" + selectedVal + "']");
var optionGroup = $(option).parents("optgroup");
var text = $(option).text();
var groupText = optionGroup.attr("label");
if (groupText && groupText != text) {
text = groupText + " " + text;
}
chosenContainer.attr("select-val", selectedVal);
chosenContainer.html(text);
}
public static RefillOptions(selectInput: HTMLElement, options: CustomSelectOptionModel[]) {
var currentOptionList = $(selectInput).closest(".select").find(".options");
// очистить список опций выпадающего списка
$(currentOptionList).html("");
var currentOption = $(selectInput).closest(".select").find(".styledSelect");
$(currentOption).removeAttr("select-val");
$(currentOption).text("");
$(selectInput).empty();
// наполнить выпадающий список и селект опциями
$.each(options, function (i, item) {
currentOptionList.append("" + item.value + "");
var opt = document.createElement('option');
opt.value = item.id;
opt.innerHTML = item.value;
selectInput.appendChild(opt);
});
//заново инициализировать опции селекта
CustomSelectInitializer.InitCustomOptions(selectInput);
}
// Установка selectedIndex кастомного селекта в нужное значение
public static SetSelectedIndex(element: HTMLElement, value: number) {
$($(element).parent('.select')).find('.selected').removeClass('selected');
$(element).attr('selected-val', ($('option', $(element))[value] as any).value);
(element as any).selectedIndex = value;
CustomSelectInitializer.SetSelectedValue((element as any));
}
private static InitCustomOptions(select: HTMLElement) {
var $styledSelect = $(select).next('div.styledSelect');
var $list = $(select).siblings("ul.options");
var $listItems = $list.children('li:not(.groupParent)');
// Hides the unordered list when a list item is clicked and updates the styled div to show the selected list item
// Updates the select element to have the value of the equivalent option
$listItems.click(function (e) {
if (e.currentTarget.attributes['disabled']) {
return;
}
e.stopPropagation();
var $this = $(select);
var clickedElement = $(this);
clickedElement.addClass("selected").siblings().removeClass("selected");
var text = clickedElement.text();
var groupText = clickedElement.prevAll(".groupParent").first().text();
//Не выводим дубликат из группы и инпута Исх.версия Исх.версия
if (groupText && groupText != text) {
text = groupText + " " + text;
}
$styledSelect.text(text).removeClass('active');
$($styledSelect).parent('.select').next('label.input-icon').removeClass('active');
var currentVal = clickedElement.attr("rel");
$this.val(currentVal);
$list.hide();
$($styledSelect).attr("select-val", currentVal);
$(select).attr("selected-val", currentVal);
var $select = $(e.currentTarget).closest(".select").find("select");
var domSelect = $select[0];
var event = new Event("change");
domSelect.dispatchEvent(event);
});
}
private static openDropDownList(e, container) {
e.stopPropagation();
$('.styledSelect.active').each(function (index, element) {
$(element).removeClass('active').next('ul.options').hide();
$(element).parent('.select').next('label.input-icon').removeClass('active');
});
$(container).toggleClass('active').next('ul.options').toggle();
$(container).parent('.select').next('label.input-icon').toggleClass('active');
}
private static openDropDownListLabel(e, container, select) {
e.stopPropagation();
$(select).focus();
$('.styledSelect.active').each(function (index, element) {
$(element).removeClass('active').next('ul.options').hide();
$(element).parent('.select').next('label.input-icon').removeClass('active');
});
$(container).toggleClass('active').next('ul.options').toggle();
$(container).parent('.select').next('label.input-icon').toggleClass('active');
}
private static copyAttributes(src, dest) {
if (!src || !dest) {
return;
}
var attributes = src.prop("attributes");
$.each(attributes, function() {
dest.attr(this.name, this.value);
});
}
};