diff --git a/SearchableInput.css b/SearchableInput.css new file mode 100644 index 0000000..a3ec784 --- /dev/null +++ b/SearchableInput.css @@ -0,0 +1,37 @@ +div.searchable-input input +{ + width: 100%; + box-sizing: border-box; +} + +div.searchable-input div.items +{ + padding-top: 0.5em; + padding-bottom: 0.5em; + border: 1px solid #aaa; + /*border-top: 0;*/ + max-width: 100%; + max-height: 10em; + overflow-x: scroll; + overflow-y: scroll; + position: absolute; + background: #fff; + box-sizing: border-box; +} + +div.searchable-input div.item +{ + white-space: normal; + padding-left: 0.5em; + padding-right: 0.5em; + user-select: none; +} + +div.searchable-input div.item:hover +{ + /*background: #0af; + color: #fff;*/ + background: highlight; + color: highlighttext; + cursor: pointer; +} diff --git a/SearchableInput.js b/SearchableInput.js new file mode 100644 index 0000000..bf0e050 --- /dev/null +++ b/SearchableInput.js @@ -0,0 +1,206 @@ +$(function() { + SearchableInput = {}; + + SearchableInput.initItems = function() + { + var items = $("div.searchable-input div.item"); + + items.each(function(i, x) { + x = $(x); + + var parent = x.parents("div.searchable-input").first(); + var input = parent.find("input").first(); + var item = x; + var itemContainer = parent.find("div.items").first(); + + if (item.is("[onclick]")) + return; + + if (!item.is("[data-value]")) + return; + + item.unbind("mousedown"); + item.bind("mousedown", function() { + input.attr("data-value", item.attr("data-value")); + input.val(item.text().trim()); + itemContainer.hide(); + }); + }); + }; + + SearchableInput.init = function() + { + $("div.searchable-input input").each(function(i, x) { + x = $(x); + + var parent = x.parents("div.searchable-input").first(); + var backgroundColor = null; + var selectColor = null; + var input = x; + var itemContainer = parent.find("div.items").first(); + var items = itemContainer.find("div.item"); + var strictSearch = parent.attr("strict-search"); + + // Get first opaque body color: + parent.parents("*").each(function(i, x) { + if (backgroundColor !== null) + return; + + x = $(x); + var color = x.css("backgroundColor"); + + if (/^rgba/.test(color)) + { + var alphaPart = parseFloat(color.split(",")[3]); + + if (isNaN(alphaPart)) + return; + + if (alphaPart > 0.9) + backgroundColor = color; + + return; + } + + if (/^rgb/.test(color)) + backgroundColor = color; + }); + + itemContainer.hide(); + + x.unbind("blur"); + x.bind("blur", function() { + setTimeout(function() { + itemContainer.hide(); + + if (input.val().trim().length < 1) + input.attr("data-value", null); + }, 10); + }); + + x.unbind("input"); + x.bind("input", function() { + + var fnOnInputCooldown = function(itemContainer) + { + var parent = itemContainer.parents("div.searchable-input").first(); + var input = parent.find("input").first(); + var items = itemContainer.find("div.item"); + var searchTermsString = input.val().toLowerCase().trim(); + var searchTerms = searchTermsString.split(" "); + + items.hide(); + + items.each(function(i, x) { + x = $(x); + + var item = x; + var pass = 1; + var itemText = item.text().toLowerCase().trim(); + + if (strictSearch) + { + if (itemText.includes(searchTermsString)) + item.show(); + return; + } + + for (var i = 0; i < searchTerms.length; i++) + { + var searchTerm = searchTerms[i]; + if (searchTerm.length < 1) + continue; + if (!itemText.includes(searchTerm)) + pass = 0; + } + + //item.hide(); + + if (pass == 1) + item.show(); + }); + }; + + + var dataSourceApi = itemContainer.attr("data-source-api"); + + if (dataSourceApi) + { + if (typeof(SearchableInput.timeout) !== "undefined") + clearTimeout(SearchableInput.timeout); + + SearchableInput.timeout = setTimeout(function() { + var searchTermsString = input.val().toLowerCase().trim(); + + console.log(dataSourceApi); + + $.get({ + url: `${dataSourceApi}?q=${searchTermsString}`, + //url: `${dataSourceApi}`, + method: "get", + success: function(data) + { + console.log(data); + itemContainer.html(""); + + for (var i = 0; i < data.length; i++) + { + var item = data[i]; + var itemElement = $("
"); + + itemElement.addClass("item"); + itemElement.attr("data-value", item.value); + itemElement.html(item.name); + + itemContainer.append(itemElement); + } + + SearchableInput.initItems(); + + fnOnInputCooldown(itemContainer); + }, + error: function(xhr, e, m) + { + console.log(e); + console.log(m); + } + }); + }, 1000); + } + + fnOnInputCooldown(itemContainer); + }); + + x.unbind("focus"); + x.bind("focus", function() { + //x.trigger("input"); + + itemContainer.css("width", parent.width() + "px"); + itemContainer.css("background", backgroundColor); + + // If data-source is a valid jQuery selector, use that container's innerHTML: + var dataSource = itemContainer.attr("data-source"); + + if (dataSource) + { + var dataSourceObject = $(dataSource); + if (dataSourceObject.length > 0) + { + itemContainer.html(dataSourceObject.first().html()); + //SearchableInput.init(); + SearchableInput.initItems(); + } + } + + itemContainer.show(); + items.show(); + input.select(); + + }); + + SearchableInput.initItems(); + }); + }; + + SearchableInput.init(); +}); diff --git a/data.json b/data.json new file mode 100644 index 0000000..a158fd8 --- /dev/null +++ b/data.json @@ -0,0 +1,8 @@ +[ + {"name": "Item 1", "value": 0}, + {"name": "Item 2", "value": 1}, + {"name": "Item 3", "value": 2}, + {"name": "Item 4", "value": 3}, + {"name": "Item 5", "value": 4}, + {"name": "Item 6", "value": 5} +] diff --git a/index.html b/index.html new file mode 100644 index 0000000..583f641 --- /dev/null +++ b/index.html @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Selection 1 +
+ +
+
+
Selection 2 +
+ +
+
+
Selection 3 +
+ +
+
+
Selection 4 +
+ +
+
+
Selection 5 +
+ +
+
+
+ +
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
+
+ + + +