Computer
jQuery custom select
// v.1 - 2021-02-08
// v.1.1 - 2021-02-09
// v.1.2 - 2021-03-07
// v.1.3 - 2021-03-10
/*
// Set default global styles
var defaults = {
".customSelect-selected" : {
"border-color" : "black",
"background-color" : "white"
},
".customSelect-items" : {
"border-color" : "black",
"background-color" : "white"
},
".customSelect-item" : {
"border-color" : "gray"
},
".customSelect-item:hover" : {
"background-color" : "lightgray"
},
".customSelect-selected::after": {
"border-color" : "black"
},
".customSelect-selected::after": {
"border-top-color" : "black"
},
".customSelect-selected.customSelect-open::after": {
"border-bottom-color": "black"
}
};
jQuery.fn.customSelect(defaults);
var options = {
"optionHeight" : "30px",
"optionsHeight": "120px",
"optionsWidth" : "none"
};
$("SELECT").customSelect(options);
*/
jQuery.fn.customSelect = function (options) {
var $ = jQuery;
if($.fn.customSelect.registered !== true) {
$.fn.customSelect.registered = true;
$('<STYLE>')
.prop('title', 'jQuery.fn.customSelect')
.prop('type' , 'text/css')
.html(
'.customSelect-selected {\n' +
'display: inline-block;\n' +
'box-sizing: border-box;\n' +
'border: 1px solid transparent;\n' +
'border-color: #000;' +
'width: 100%;\n' +
'background-color: #FFF;' +
'cursor: pointer;\n' +
'}\n' +
'.customSelect-selected-value {\n' +
'float: left;\n' +
'width: calc(100% - 14px);\n' +
'overflow: hidden;\n' +
'text-overflow: ellipsis;\n' +
'white-space: nowrap;\n' +
'}\n' +
'.customSelect-items {\n' +
'position: absolute;\n' +
'box-sizing: border-box;\n' +
'margin-top: -1px;\n' +
'border: 1px solid transparent;\n' +
'border-color: #000;' +
'background-color: #FFF;' +
'overflow: auto;\n' +
'z-index: 10000;\n' +
'}\n' +
'.customSelect-group {\n' +
'box-sizing: border-box;\n' +
'border: 1px solid transparent;\n' +
'overflow: hidden;\n' +
'text-overflow: ellipsis;\n' +
'cursor: pointer;\n' +
'user-select: none;\n' +
'}\n' +
'.customSelect-item {\n' +
'box-sizing: border-box;\n' +
'border: 1px solid transparent;\n' +
'overflow: hidden;\n' +
'text-overflow: ellipsis;\n' +
'cursor: pointer;\n' +
'user-select: none;\n' +
'}\n' +
'.customSelect-item-selected {\n' +
'font-weight: bold;\n' +
'}\n' +
'.customSelect-item:hover {\n' +
'background-color: #EEE;\n' +
'}\n' +
'.customSelect-selected::after {\n' +
'margin: 6px 2px -6px 0;\n' +
'border: 6px solid transparent;\n' +
'border-top-color: #000;\n' +
'border-right-color: transparent !important;\n' +
'border-bottom-color: transparent;\n' +
'border-left-color: transparent !important;\n' +
'width: 0;\n' +
'height: 0;\n' +
'display: inline-block;\n' +
'float: right;\n' +
'vertical-align: top;\n' +
'content: "";\n' +
'}\n' +
'.customSelect-selected.customSelect-open::after {\n' +
'margin-top: 0;\n' +
'border-top-color: transparent !important;\n' +
'border-bottom-color: #000;\n' +
'vertical-align: bottom;\n' +
'}\n'
)
.prependTo('HEAD')
;
$(window).on("click" , function (events) {
var element = $(events.target);
if(!element.hasClass("customSelect-selected" )
&& !element.hasClass("customSelect-selected-value")
&& !element.hasClass("customSelect-items" )
&& !element.hasClass("customSelect-item" )
) $(".customSelect-selected.customSelect-open").trigger("click");
});
setInterval(function () {
$(".customSelect-items").each(function () {
if($("." + $(this).data("customSelect")).length == 0) {
$(this).remove();
}
});
}, 1000);
}
if(this === jQuery.fn) {
if(typeof(options) == "object") {
$(document.styleSheets).each(function (n, style) {
if(style.title == "jQuery.fn.customSelect") {
var rules = style.cssRules || style.rules;
for(var i = 0; i < rules.length; i++) {
for(var j in options) {
if(rules[i].selectorText == j
&& typeof(options[j]) == "object"
) {
for(var k in options[j]) {
rules[i].style[k] = options[j][k];
}
}
}
}
return false;
}
});
}
return;
}
return $(this).each(function () {
var select = $(this);
if(!select.is("SELECT")
|| select.data("customSelect") == true
) return;
var customSelect = $("<DIV>").addClass("customSelect-selected" ).uniqueClass(null, "customSelect-unique-");
var customSelectValue = $("<DIV>").addClass("customSelect-selected-value" )
var customSelectItems = $("<DIV>").addClass("customSelect-items customSelect-hide").hide(0);
var uniqueClass = customSelect.data("unique-class-name");
var text = "";
var selectedIndex = select.get(0).selectedIndex;
if(selectedIndex > -1) {
text = select.find("OPTION").eq(selectedIndex).text();
}
customSelectValue
.prop("title", text)
.text( text || " ")
;
customSelect
.append(customSelectValue)
.data("custom-select-options", $.extend({
optionHeight : "none",
optionsHeight: "none",
optionsWidth : "none"
}, options))
.css("position", select.css("position"))
.css("z-index" , select.css("z-index" ))
.css("top" , select.css("top" ))
.css("left" , select.css("left" ))
.css("margin" , select.css("margin" ))
.css("width" , select.css("width" ))
.on("click", function () {
if(customSelectItems.hasClass("customSelect-hide")) {
$(".customSelect-selected.customSelect-open").trigger("click");
var selectedIndex = select.get(0).selectedIndex;
var scrollTo = $();
var withGroup = (select.find("OPTGROUP").length > 0);
var index = 0;
select.find("OPTGROUP, OPTION").each(function () {
var $this = $(this);
var text = $this.text();
var option = $("<DIV>")
.css("max-height", customSelect.data("custom-select-options").optionHeight)
.prop("title", text)
.text( text || " ")
;
if($this.is("OPTGROUP")) {
option
.addClass("customSelect-group")
;
} else {
option
.addClass("customSelect-item")
.data("custom-select-index", index)
.on("click", function () {
var index = $(this).data("custom-select-index");
if(select.get(0).selectedIndex != index) {
select.get(0).selectedIndex = index;
select.trigger("change");
}
customSelectValue
.prop("title", option.prop("title"))
.text( option.text( ))
;
customSelect.trigger("click");
})
;
if(withGroup) {
option.css("padding-left", (parseFloat(option.css("padding-left").replace("px", "") || 0) + 10) + "px");
}
if(index == selectedIndex) {
scrollTo = option.addClass("customSelect-item-selected");
}
index++;
}
customSelectItems.append(option);
});
var offset = customSelect
.addClass("customSelect-open")
.offset()
;
customSelectItems
.css("max-height", "auto")
.css("max-width" , "auto")
.width(customSelect.outerWidth() - (customSelectItems.outerWidth() - customSelectItems.width()))
.css("top" , (offset.top + customSelect.outerHeight()) + "px")
.css("left" , offset.left + "px")
.css("max-height", customSelect.data("custom-select-options").optionsHeight)
.css("max-width" , customSelect.data("custom-select-options").optionsWidth )
.removeClass("customSelect-hide")
.show("slow", function () {
customSelectItems.scrollTop(customSelectItems.scrollTop() + (scrollTo.position() || {top:0}).top);
})
;
} else {
customSelect
.removeClass("customSelect-open")
;
customSelectItems
.hide("slow", function () {
customSelectItems
.offset({top: 0, left: 0 })
.addClass("customSelect-hide")
.empty()
;
})
;
}
})
.insertAfter(select.hide(0))
;
$("BODY")
.append(customSelectItems
.data("customSelect", uniqueClass)
)
;
});
};
jQuery.fn.uniqueClass = function () {
var $ = jQuery;
var length = Math.max(10, parseInt((arguments[0] || 32 )));
var prefix = (arguments[1] || "unique-" ).toString();
var sufix = (arguments[2] || "" ).toString();
var chars = (arguments[3] || "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789").toString();
var tries = Math.max( 1, parseInt((arguments[4] || 10 )));
return $(this).each(function () {
var className = "";
var found = true;
for(var i = 0; i < tries && found; i++) {
for(var j = 0; j < length; j++) {
className+= chars[parseInt(Math.random() * chars.length)];
}
className = prefix + className + sufix;
found = ($("." + className).length > 0);
}
if(!found) {
$(this)
.addClass(className)
.data("unique-class-name", className)
;
}
});
};
<select id="example">
<optgroup>Group 1</optgroup>
<option value="value1_1">Option 1.1</option>
<option value="value1_2">Option 1.2</option>
<option value="value1_3">Option 1.3</option>
<optgroup>Group 2</optgroup>
<option value="value2_1">Option 2.1</option>
<option value="value2_2">Option 2.2</option>
<option value="value2_3">Option 2.3</option>
</select>
<script type="text/javascript">
var defaults = {
".customSelect-selected" : {
"border-color" : "red",
"background-color": "white",
"color" : "black",
"text-align" : "left"
},
".customSelect-items" : {
"border-color" : "red",
"background-color": "white",
"color" : "black"
},
".customSelect-group" : {
"border-color" : "gray"
},
".customSelect-item" : {
"border-color" : "gray"
},
".customSelect-item:hover" : {
"background-color": "lightgray"
},
".customSelect-selected::after": {
"border-top-color" : "red"
},
".customSelect-selected.customSelect-open::after": {
"border-bottom-color" : "red"
}
};
jQuery.fn.customSelect(defaults);
var options = {
"optionHeight" : "30px",
"optionsHeight": "120px",
"optionsWidth" : "250px"
};
$("#example")
.width("300px")
.customSelect(options)
;
</script>
USE IT AT YOUR OWN RISK!