bitbake: toaster: migrate typeahead library

Migrate from Bootstrap 2's built-in typeahead to Twitter's
typeahead library.

This is to facilitate moving to Bootstrap 3, which doesn't have
a typeahead.

(Bitbake rev: 0748177b40188a6fb735fe1ba1c17294afa4a3d0)

Signed-off-by: Elliot Smith <elliot.smith@intel.com>
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Elliot Smith 2016-04-12 12:07:01 +01:00 committed by Richard Purdie
parent 64622029d7
commit cd7b48cd0d
5 changed files with 84 additions and 68 deletions

View File

@ -9,4 +9,6 @@ Foundation and individual contributors.
* jQuery is redistributed under the MIT license. * jQuery is redistributed under the MIT license.
* Twitter typeahead.js redistributed under the MIT license.
* QUnit is redistributed under the MIT license. * QUnit is redistributed under the MIT license.

View File

@ -341,3 +341,22 @@ input.input-lg {
line-height: 1.33333; line-height: 1.33333;
padding: 10px 16px; padding: 10px 16px;
} }
/* styling for standalone typeahead library */
.tt-menu {
margin-top: 2px;
border-radius: 4px;
width: 100%;
}
.tt-suggestion {
cursor: pointer;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.tt-suggestion.active {
background-color: #0081c2;
color: white;
}

View File

@ -3,96 +3,82 @@
* This object really just helps readability since we can then have * This object really just helps readability since we can then have
* a traceable namespace. * a traceable namespace.
*/ */
var libtoaster = (function (){ var libtoaster = (function () {
// prevent conflicts with Bootstrap 2's typeahead (required during
// transition from v2 to v3)
var typeahead = jQuery.fn.typeahead.noConflict();
jQuery.fn._typeahead = typeahead;
/* makeTypeahead parameters /* Make a typeahead from an input element
* elementSelector: JQuery elementSelector string *
* xhrUrl: the url to get the JSON from expects JSON in the form: * _makeTypeahead parameters
* { "list": [ { "name": "test", "detail" : "a test thing" }, .... ] } * jQElement: input element as selected by $('selector')
* xhrUrl: the url to get the JSON from; this URL should return JSON in the
* format:
* { "results": [ { "name": "test", "detail" : "a test thing" }, ... ] }
* xhrParams: the data/parameters to pass to the getJSON url e.g. * xhrParams: the data/parameters to pass to the getJSON url e.g.
* { 'type' : 'projects' } the text typed will be passed as 'search'. * { 'type' : 'projects' }; the text typed will be passed as 'search'.
* selectedCB: function to call once an item has been selected one * selectedCB: function to call once an item has been selected; has
* arg of the item. * signature selectedCB(item), where item is an item in the format shown
* in the JSON list above, i.e.
* { "name": "name", "detail": "detail" }.
*/ */
function _makeTypeahead (jQElement, xhrUrl, xhrParams, selectedCB) { function _makeTypeahead(jQElement, xhrUrl, xhrParams, selectedCB) {
if (!xhrUrl || xhrUrl.length === 0) if (!xhrUrl || xhrUrl.length === 0) {
throw("No url to typeahead supplied"); throw("No url supplied for typeahead");
}
var xhrReq; var xhrReq;
jQElement.typeahead({ jQElement._typeahead(
// each time the typeahead's choices change, a {
// "typeahead-choices-change" event is fired with an object highlight: true,
// containing the available choices in a "choices" property classNames: {
source: function(query, process){ open: "dropdown-menu",
cursor: "active"
}
},
{
source: function (query, syncResults, asyncResults) {
xhrParams.search = query; xhrParams.search = query;
/* If we have a request in progress don't fire off another one*/ // if we have a request in progress, cancel it and start another
if (xhrReq) if (xhrReq) {
xhrReq.abort(); xhrReq.abort();
}
xhrReq = $.getJSON(xhrUrl, this.options.xhrParams, function(data){ xhrReq = $.getJSON(xhrUrl, xhrParams, function (data) {
if (data.error !== "ok") { if (data.error !== "ok") {
console.log("Error getting data from server "+data.error); console.error("Error getting data from server: " + data.error);
return; return;
} }
xhrReq = null; xhrReq = null;
jQElement.trigger("typeahead-choices-change", {choices: data.results}); asyncResults(data.results);
return process(data.results);
}); });
}, },
updater: function(item) {
var itemObj = this.$menu.find('.active').data('itemObject'); // how the selected item is shown in the input
selectedCB(itemObj); display: function (item) {
return item; return item.name;
}, },
matcher: function(item) {
if (!item.hasOwnProperty('name')) { templates: {
console.log("Name property missing in data"); // how the item is displayed in the dropdown
return 0; suggestion: function (item) {
var elt = document.createElement("div");
elt.innerHTML = item.name + " " + item.detail;
return elt;
} }
}
}
);
if (this.$element.val().length === 0) // when an item is selected using the typeahead, invoke the callback
return 0; jQElement.on("typeahead:select", function (event, item) {
selectedCB(item);
return 1;
},
highlighter: function (item) {
/* Use jquery to escape the item name and detail */
var current = $("<span></span>").text(item.name + ' '+item.detail);
current = current.html();
var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
return current.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
return '<strong>' + match + '</strong>'
})
},
sorter: function (items) { return items; },
xhrUrl: xhrUrl,
xhrParams: xhrParams,
xhrReq: xhrReq,
}); });
/* Copy of bootstrap's render func but sets selectedObject value */
function customRenderFunc (items) {
var that = this;
items = $(items).map(function (i, item) {
i = $(that.options.item).attr('data-value', item.name).data('itemObject', item);
i.find('a').html(that.highlighter(item));
return i[0];
});
items.first().addClass('active');
this.$menu.html(items);
return this;
}
jQElement.data('typeahead').render = customRenderFunc;
} }
/* startABuild: /* startABuild:

File diff suppressed because one or more lines are too long

View File

@ -21,6 +21,8 @@
</script> </script>
<script src="{% static 'js/bootstrap.min.js' %}"> <script src="{% static 'js/bootstrap.min.js' %}">
</script> </script>
<script src="{% static 'js/typeahead.jquery.min.js' %}">
</script>
<script src="{% static 'js/prettify.js' %}"> <script src="{% static 'js/prettify.js' %}">
</script> </script>
<script src="{% static 'js/libtoaster.js' %}"> <script src="{% static 'js/libtoaster.js' %}">