JSFiddle - React, Tailwind, and code Playground
by whelkaholism
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.1/knockout-latest.js"></script>
<script src="https://cdn.cfront-cloud.co.uk/scripts/koa1.2/cf.DOM.js"></script>
<script src="https://cdn.cfront-cloud.co.uk/scripts/koa1.2/cf.linq.js"></script>
<input data-bind="lookup: { boundField: Value, source: Src, allowDropDown: true }"/>
<div data-bind="text: ko.toJSON(Value)"></div>
CSS
.section > div:not(.group) > div.koa-lookup,
.koa-lookup {
display: inline-block;
position: relative;
box-sizing: border-box;
width: fit-content;
}
.koa-lookup .koa-lookup-items {
display: none;
position: absolute;
left: 0;
z-index: 1;
}
.koa-lookup .koa-lookup-items.loading {
display: block;
}
.koa-lookup .koa-lookup-items.show {
display: block;
}
.koa-lookup .koa-lookup-items.loading li:not(.loading) {
display: none;
}
.koa-lookup .koa-lookup-items.show li.loading {
display: none;
}
.koa-lookup .koa-lookup-items.show {
display: block;
background: #ffffffff;
padding: 0.5em;
border: 1px solid #dddddd;
border-top: none;
}
.koa-lookup .koa-lookup-items li {
padding: 0.25em;
}
.koa-lookup .koa-lookup-items li:hover,
.koa-lookup .koa-lookup-items li.active {
background: #cccccc;
}
.koa-lookup .koa-lookup-items l.current {
background: #cccccc;
border-left: 3px solid #404040;
}
.koa-lookup input {
width: 100%;
}
.koa-lookup .koa-lookup-items {
max-height: 40em;
overflow-y: auto;
}
.koa-lookup { display: flex }
.koa-lookup-dropdown::before { content: 'V'}
.koa-lookup.is-shown .koa-lookup-dropdown::before { content: '^'}
JavaScript
(function()
{
var _getConfig = function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext)
{
var o = ko.unwrap(f_valueaccessor());
var res = {
obs: o.boundField,
idobs: o.boundIDField,
idField: 'ID',
valueField: 'Name',
source: o.source,
itemTemplate: o.itemTemplate || '<li>{{Name}}</li>',
valueTemplate: o.itemTemplate || '{{Name}}',
rateLimit: typeof (o.rateLimit) != 'undefined' ? o.rateLimit : 300,
renderItem: o.renderItem,
selected: o.selected,
allowDropDown: !!o.allowDropDown,
_input: el
};
return res;
};
var _populateTemplate = function(template, item, cfg)
{
var res = (template || '').replace(/\{\{([^\}]+)\}\}/, function(m, g1)
{
var repres = item && ko.unwrap(item[g1]);
return repres || '';
});
return res || '';
};
var _callSource = function(term, cfg)
{
return new Promise(function(resolve)
{
var res = null;
var a = null;
if (ko.isObservableArray(cfg.source))
a = cfg.source();
else if (typeof (cfg.source) == 'function')
cfg.source(term).then(resolve);
else
a = cfg.source;
if (a != null)
{
res = a.where(cfg.predicate || function(x)
{
return new RegExp(term, 'i').test(typeof (x) == 'string' ? x : (x && x[cfg.valueField]));
});
}
if (res != null)
resolve(res);
});
};
var _renderItem = function(item, cfg)
{
if (cfg.renderItem)
return cfg.renderItem(item, cfg);
else
return _populateTemplate(cfg.itemTemplate,...