Last active
December 19, 2015 13:59
-
-
Save mollwe/5965647 to your computer and use it in GitHub Desktop.
Replaces select (dropdowns) with a stylable jQuery UI widget that uses autocomplete.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.ui-combobox { | |
position: relative; | |
display: inline-block; | |
} | |
.ui-combobox-toggle { | |
width:1.5em; | |
right:-1px; | |
position: absolute !important; | |
top: 0; | |
bottom: 0; | |
margin-left: -1px; | |
padding: 0; | |
/* adjust styles for IE 6/7 */ | |
*height: 1.7em; | |
*top: 0.1em; | |
} | |
.ui-combobox-input { | |
background: white !important; | |
margin: 0; | |
padding: .3em 1.5em .3em .3em; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* jquery.ui.combobox.js - v 0.1 (2013-07-10) | |
* Copyright (C) 2013 by Adam Ydenius ([email protected]) | http://mollwe.se | |
* Dual licensed under MIT and GPL. | |
*/ | |
/* | |
* Replaces select (dropdowns) with a stylable jQuery UI widget that uses autocomplete. | |
* | |
* Selects that has been enabled with this plugin has class "ui-combobox-target". | |
* | |
* To enable plugin call combobox on the elements you would like to transform. | |
* Example: $("select:not(.no-ui-combobox)").combobox(); | |
* | |
* Dependencies: | |
* jquery | |
* jquery.ui | |
*/ | |
(function (factory) { | |
if (typeof define === 'function' && define.amd) { | |
// AMD. Register as an anonymous module. | |
define(['jquery', 'jquery-ui'], factory); | |
} else { | |
// Browser globals | |
factory(jQuery); | |
} | |
} (function ($) { | |
$.widget("ui.combobox", { | |
_create: function () { | |
var input, | |
that = this, | |
width = this.element.width(), | |
select = this.element.attr("tabindex", -1).addClass("ui-combobox-target ui-helper-hidden-accessible"), | |
disabled = select.is(":disabled"), | |
selected = select.children(":selected"), | |
empty = select.children("option[value=]"), | |
value = selected.val() !== "" ? selected.text() : "", | |
wrapper = this.wrapper = $("<span>") | |
.addClass("ui-combobox") | |
.css("margin", select.css("margin")) | |
.insertAfter(select); | |
function removeIfInvalid(element) { | |
var value = $(element).val(), | |
matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(value) + "$", "i"), | |
valid = false; | |
select.children("option").each(function () { | |
var text = $(this).text(); | |
if (text.match(matcher)) { | |
valid = true; | |
$(element).val(text); | |
$(element).data("value", this.value); | |
if (this.selected !== true) { | |
this.selected = true; | |
select.change(); | |
} | |
return false; | |
} | |
}); | |
if (!valid) { | |
// remove invalid value, as it didn't match anything | |
select.change(); | |
return false; | |
} | |
} | |
input = $("<input>") | |
.appendTo(wrapper) | |
.val(value) | |
.attr("title", "") | |
.attr("disabled", disabled) | |
.attr("spellcheck", false) | |
.attr("placeholder", empty.text()) | |
.attr("data-value", select.val()) | |
.addClass("ui-state-default ui-combobox-input") | |
.width(width - 20) | |
//.focus(function(){ | |
// input.autocomplete("search", ""); | |
//}) | |
.autocomplete({ | |
delay: 0, | |
minLength: 0, | |
autoFocus: true, | |
source: function (request, response) { | |
var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i"); | |
var filtered = select.children("option").map(function () { | |
var text = $(this).text(); | |
if (!this.value && !request.term || this.value && (!request.term || matcher.test(text))) | |
return { | |
label: text.replace( | |
new RegExp( | |
"(?![^&;]+;)(?!<[^<>]*)(" + | |
$.ui.autocomplete.escapeRegex(request.term) + | |
")(?![^<>]*>)(?![^&;]+;)+", "gi" | |
), "<strong>$1</strong>"), | |
value: this.value === "" ? "" : text, | |
option: this | |
}; | |
}); | |
if (request.term !== null && request.term !== undefined && request.term.length) { | |
filtered = filtered.sort(function (a, b) { | |
var aIndex = a.value.indexOf(request.term), | |
bIndex = b.value.indexOf(request.term); | |
if (aIndex == bIndex) { | |
if (a.value.length == b.value.length) { | |
//console.debug("value", a.value, b.value, a.value > b.value ? b.value : a.value); | |
return a.value > b.value ? 1 : a.value < b.value ? -1 : 0; | |
} | |
//console.debug("length", a.value, a.value.length, b.value, b.value.length, a.value.length > b.value.length ? b.value : a.value); | |
return a.value.length - b.value.length; | |
} | |
//console.debug("index", a.value, aIndex, b.value, bIndex, aIndex > bIndex ? b.value : a.value); | |
return aIndex - bIndex; | |
}); | |
} | |
response(filtered); | |
}, | |
select: function (event, ui) { | |
var changed = !ui.item.option.selected; | |
ui.item.option.selected = true; | |
that._trigger("selected", event, { | |
item: ui.item.option | |
}); | |
if (changed) selected.change(); | |
}, | |
change: function (event, ui) { | |
if (!ui.item) | |
return removeIfInvalid(this); | |
} | |
}) | |
.addClass("ui-widget ui-widget-content ui-corner-left") | |
.on("blur.combobox", function () { | |
setTimeout(function () { | |
select.blur(); | |
}, 0); | |
}); | |
var autocomplete = input.data("autocomplete"); | |
autocomplete._renderItem = function (ul, item) { | |
return $("<li>") | |
.data("item.autocomplete", item) | |
.append("<a>" + item.label + "</a>") | |
.appendTo(ul); | |
}; | |
var button = $("<a>") | |
.attr("tabIndex", -1) | |
//.attr("title", "Show All Items") | |
//.tooltip() | |
.appendTo(wrapper) | |
.button({ | |
icons: { | |
primary: "ui-icon-triangle-1-s" | |
}, | |
disabled: disabled, | |
text: false | |
}) | |
.removeClass("ui-corner-all") | |
.addClass("ui-corner-right ui-combobox-toggle") | |
.click(function () { | |
if (!$(this).button("option", "disabled")) { | |
// close if already visible | |
if (input.autocomplete("widget").is(":visible")) { | |
input.autocomplete("close"); | |
removeIfInvalid(input); | |
return; | |
} | |
// work around a bug (likely same cause as #5265) | |
$(this).blur(); | |
// pass empty string as value to search for, displaying all results | |
input.autocomplete("search", ""); | |
input.focus(); | |
} | |
}); | |
var data = { input: input, select: select, button: button, autocomplete: autocomplete }; | |
select.data("combobox", data); | |
input.data("combobox", data); | |
select.on("change.combobox", function () { | |
var value = select.val(); | |
//if (value !== inputValue) { | |
var option = select.children("option[value='" + value + "']:first"); | |
var text = option.text() || value; | |
input.val(value !== "" ? text : ""); | |
input.data("autocomplete").term = text; | |
input.data("value", value); | |
//} | |
select.blur(); | |
}); | |
}, | |
refresh: function () { | |
var combobox = this.element.data("combobox"); | |
if (combobox.select.is(":disabled")) { | |
combobox.input.attr("disabled", true); | |
combobox.button.button("disable"); | |
} | |
else { | |
combobox.input.attr("disabled", false); | |
combobox.button.button("enable"); | |
} | |
combobox.input.val(combobox.select.val() || ""); | |
}, | |
disable: function () { | |
var combobox = this.element.data("combobox"); | |
combobox.input.attr("disabled", true); | |
combobox.button.button("disable"); | |
}, | |
enable: function () { | |
var combobox = this.element.data("combobox"); | |
combobox.input.attr("disabled", false); | |
combobox.button.button("enable"); | |
}, | |
destroy: function () { | |
this.wrapper.remove(); | |
this.element.show(); | |
$.Widget.prototype.destroy.call(this); | |
} | |
}); | |
})); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment