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!
Kudos: 0 [Give a kudo]

12r6j5xasef5Z6Sm4A6oBpMLn2ESPPX6ym
Ads: