此代码完美无缺。但建议的文字无法使用键盘控制 当箭头键上下。我想用键盘控制这个建议的文字 我怎样才能做到这一点。请帮助..................
/*
*
* jQuery MultiComplete
* =====================
* Written by Tom Hallam
* http://tomhallam.github.com/jQuery-Multicomplete/
* Licenced with the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) licence
* See: http://creativecommons.org/licenses/by-sa/3.0/
*
*/
(function ($) {
$.fn.multicomplete = function (options) {
// Set up the default options
var defaults = {
// Debug mode provides verbose error messages
debug: true,
// Source
source: [],
// AJAX Method (if source is a URL)
method: 'POST',
// Minimum length before a search can be triggered
minimum_length: 3,
// Delay before performing a search, ignored if source is local
search_delay: 500,
// Case sensitive search?
case_sensitive: false,
// Highlight found words?
highlight_results: true,
// Left offset for results panel
offset_left: 0,
// Top offset for results panel
offset_top: 5,
// Result template
result_template: function(row) {
// -- Please fill this in!
},
// Events -------
// On result click
result_click: null,
// On form submit
form_submit: null
},
// Extend the base object
settings = $.extend(defaults, options);
// Object to keep track of our timers
var timers = [],
// And our result groups
groups = {},
// The results themselves
results = [],
// And the query
query = '';
// Iterate over the selected elements and apply the behavior.
return this.each(function () {
multicomplete_init($(this));
});
// Bootstrapper function to attach events to the elements selected
function multicomplete_init(el) {
// Create a unique ID for this element
id = 'multicomplete-' + Math.floor(Math.random() * 1000);
$(el).data('multicomplete-id', id);
// Make a new key in our timer object
timers[id] = {};
// We need to set a timer for input to trigger based on a delay
$(el).on('keyup', function() {
// Keep a local copy of the value
query = $(this).val();
// Clear any old timers
window.clearTimeout(timers[id]);
// If there's nothing left in the input box, do nothing and hide my result panel
if(query.length == 0) {
$('.panel-multicomplete-results.' + id).hide();
return;
}
// Reset the results array
results = [];
// Make sure the query is hitting the minimum length constraint
if(query.length > settings.minimum_length) {
// Where are we sending this search?
switch(typeof(settings.source)) {
case 'string':
timers[id] = window.setTimeout(function(){
multicomplete_searchajax(function() {
multicomplete_render(el);
});
}, settings.search_delay);
break;
case 'object':
multicomplete_searchobject();
multicomplete_render(el);
break;
}
}
}).attr('autocomplete', 'off');
// Hide the DIV when someone clicks outside of the result pane.
$(document).on('mouseup', function(e) {
if($('.panel-multicomplete-results.' + id).has(e.target).length === 0) {
$('.panel-multicomplete-results.' + id).hide();
}
});
}
// Parse a result group
function multicomplete_parsegroup(group_results, group_name) {
// Loop through the group
$(group_results).each(function(index, row) {
for(var field in row) {
// No numbers (for now)
if(typeof row[field] == 'number') {
return true;
}
if(typeof row[field] == 'object') {
multicomplete_parsegroup(row);
}
else {
// If we find a result then push into our results array.
if(multicomplete_match(row[field])) {
results.push({
'field': field,
'row': row,
'group': group_name
});
return true;
}
}
}
});
}
// Does this string match the query
function multicomplete_match(field) {
if(settings.case_sensitive == true) {
return field.indexOf(query) > -1;
}
else {
return field.toLowerCase().indexOf(query.toLowerCase()) > -1;
}
}
// Search an object
function multicomplete_searchobject() {
if(settings.source.length == 0) {
if(settings.debug == true) {
alert('Source was set to an array, but the array was empty.');
}
}
// Loop through the source
for(var group_name in settings.source) {
if(settings.source[group_name].length)
groups[group_name] = multicomplete_parsegroup(settings.source[group_name], group_name);
}
}
// Search an AJAX endpoint
function multicomplete_searchajax(callback) {
// Perform the remote call.
ajax = $.ajax({
'type': settings.method,
'url': settings.source,
'dataType': 'json',
'data': {
'query': query
},
'success': function(data) {
// Loop through the source
for(var group_name in data) {
if(data[group_name].length)
groups[group_name] = multicomplete_parsegroup(data[group_name], group_name);
}
// Call the callback
callback.call(this, data);
},
'error': function(error) {
if(settings.debug == true) {
if(error.status == 412) {
alert('Your remote data source is not valid JSON! Remember to use double quotes instead of single.');
}
if(error.status == 404) {
alert('Your remote data source does not exist on this server.');
}
if(error.status == 500) {
alert('The remote server encountered an error whilst processing your source.');
}
}
}
});
}
// Render a search result
function multicomplete_render(el) {
// Where is the element
l = el.offset().left,
t = el.offset().top,
mc_html_class = 'panel-multicomplete-results ' + el.data('multicomplete-id'),
mc_class = '.panel-multicomplete-results.' + el.data('multicomplete-id');
// Is there already a results div for this element?
if($(mc_class).length == 0) {
// Build the div
$('<div class="' + mc_html_class + '"></div>').css({
'position': 'absolute',
'left': (l + settings.offset_left),
'top': (t + $(el).height() + settings.offset_top)
}).appendTo('body');
}
else {
$(mc_class).empty().show();
}
// Were there any results?
if(results.length == 0 && !$(mc_class + ' .panel-no-results').length) {
$('<div class="panel-no-results">No results found</div>').appendTo(mc_class);
}
else {
// Create a results div
$('<div class="results"></div>').appendTo(mc_class);
// Loop through the results and group them again
$(results).each(function(index, result) {
if($(mc_class + ' .results .' + result.group).length == 0) {
$('<div class="group ' + result.group + '"><div class="group-title">' + result.group + '</div><div class="group-items"></div></div>').appendTo(mc_class + ' .results');
}
// Cache the result row
r = $('<div class="result"></div>').appendTo(mc_class + ' .results .' + result.group + ' .group-items');
// Get the HTML for the result template
result_tmpl = settings.result_template.call(this, result.row, result.group, result.field);
// Apply the click action
$(result_tmpl).on('click', function() {
if(typeof settings.result_click == 'function') {
settings.result_click.call(this, result.row, result.group);
}
else {
multicomplete_defaultclick(result.row, result.group, el);
}
}).appendTo(r);
});
// Apply a clearfix to the groups
$('<div class="clearfix"></div>').appendTo(mc_class + ' .results .group');
// If we have the highlight option turned on then do that
if(settings.highlight_results == true) {
multicomplete_highlight($(mc_class + ' .results').get(0), query.toUpperCase());
}
}
}
// Default click action for a result
function multicomplete_defaultclick(result, group, el) {
// Is there even a form?
if($(el).closest('form').length == 0) {
}
else {
// Override the form submit to do some funky tings
$(el).closest('form').on('submit', function(e) {
// Check if we've already modified the form
if($(this).data('multicomplete-modified') == true) {
$(this).submit();
}
else {
// Stop the form from submitting
e.preventDefault();
// Modify the element
if(!!el.attr('name')) {
old_name = el.attr('name');
el.attr('name', el.attr('name' + '-mc-dummy'));
}
// Create a new hidden element with the ID
$('<input type="hidden" name="' + old_name + '" value="' + (!!result.id ? result.id : JSON.stringify(result)) + '" />').insertAfter(el);
// Add the checkpoint on to the form
$(this).data('multicomplete-modified', true);
// Submit the form
$(this).submit();
}
});
}
}
/*
highlight v3
Highlights arbitrary terms.
<http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html>
MIT license.
Johann Burkard
<http://johannburkard.de>
<mailto:jb@eaio.com>
*/
function multicomplete_highlight(node, pat) {
var skip = 0;
if (node.nodeType == 3) {
var pos = node.data.toUpperCase().indexOf(pat);
if (pos >= 0) {
var spannode = document.createElement('span');
spannode.className = 'highlight';
var middlebit = node.splitText(pos);
var endbit = middlebit.splitText(pat.length);
var middleclone = middlebit.cloneNode(true);
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode, middlebit);
skip = 1;
}
} else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
for (var i = 0; i < node.childNodes.length; ++i) {
i += multicomplete_highlight(node.childNodes[i], pat);
}
}
return skip;
}
}
})(jQuery);
$(document).ready(function() {
$('#input-multicomplete').multicomplete({
minimum_length: 1,
result_template: function(result, group, matched_field) {
tmpl = '<div>';
if(!!result.image) {
tmpl += '<div class="image"><img src="' + result.image + '" /></div>';
}
tmpl += '<div>' + result.name + '</div>';
if(!!result.address) {
tmpl += '<div class="meta">' + result.address + '</div>';
}
// Only display this field if something was matched in it
if(!!result.cuisine && matched_field == 'cuisine') {
tmpl += '<div class="cuisine">Cuisine offered: ' + result.cuisine + '</div>';
}
tmpl += '</div>';
return tmpl;
},
result_click: function(row, group) {
alert('You chose "' + row.name + '" in ' + group);
},
source: {
"Attractions": [
{
"name": "The Tower of London",
"address": "London, EC3N 4AB",
"image": "http://www.hrp.org.uk/Images/TOL_Main.jpg"
},
{
"name": "Camden Lock Market",
"address": "1 Kentish Town Road, London, NW1 8",
"image": "http://www.london-attractions.info/images/attractions/camden-market.jpg"
},
{
"name": "Anne Frank Museum",
"address": "Prinsengracht 267, 1000 AS, Amsterdam",
"image": "http://upload.wikimedia.org/wikipedia/commons/thumb/9/9c/AnneFrankHouseAmsterdamtheNetherlands.jpg/220px-AnneFrankHouseAmsterdamtheNetherlands.jpg"
}
],
"Hotels": [
{
"name": "The Ritz",
"address": "150 Piccadilly, London, W1J 9BR",
"image": "http://www.londonhotels.net/images/photogallery/the-ritz-london/the-ritz-london.jpg"
},
{
"name": "51 Buckingham Gate",
"address": "51 Buckingham Gate, London, SW1E 6AF",
"image": "http://static.laterooms.com/hotelphotos/laterooms/193559/gallery/51-buckingham-gate-london_060620111405093617.jpg"
},
{
"name": "Hotel de l'Europe",
"address": "2–14 Nieuwe Doelenstraat, Amsterdam, 1012 CP ",
"image": "http://www.concierge.com/images/cnt/lists/goldlist06/europe/netherlands/amsterdam/hotel_de_leurope/amsterdam_hotel_002p.jpg"
}
],
"Restaurant": [
{
"name": "Petrus",
"address": "1 Kinnerton Street, Knightsbridge, London, SW1X 8EA",
"image": "http://berkshirereview.net/images/petrus_london_dining.jpg"
},
{
"name": "Vermeer",
"address": "Prins Hendrikkade 59-72, 1012 AD Amsterdam ",
"image": "http://www.restaurantvermeer.nl/Portals/7/UltraPhotoGallery/3425/45/[7].Vermeer---desert-2.jpg"
}
]
}
});
});
&#13;
/* DEMO STYLES */
.result .image {
float: left;
margin-right: 10px;
}
.result .image img {
width: 32px;
height: 32px;
border: 1px solid #ccc;
padding: 1px;
}
.result .meta {
font-size: 11px;
color: #666;
}
.result a {
text-decoration: underline;
}
.result:hover {
background-color: #f7f7f7;
}
/*
*
* jQuery MultiComplete
* =====================
* Written by Tom Hallam
* http://tomhallam.github.com/jQuery-Multicomplete/
* Licenced with the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) licence
* See: http://creativecommons.org/licenses/by-sa/3.0/
*
*/
.panel-multicomplete-results {
border: 1px solid #ccc;
width: 420px;
font-family: Tahoma;
font-size: 12px;
background: url(mc-bg.png) repeat-y;
}
.panel-multicomplete-results .result {
padding: 5px;
border-bottom: 1px solid #e7e7e7;
cursor: pointer;
}
.panel-multicomplete-results .result:last-child {
border: none;
}
.panel-multicomplete-results .group {
border-bottom: 1px solid #ccc;
}
.panel-multicomplete-results .group:last-child {
border: none;
}
.panel-multicomplete-results .group-title {
float: left;
width: 100px;
padding: 5px;
font-weight: bold;
}
.panel-multicomplete-results .group-items {
float: left;
width: 300px;
}
.highlight {
font-weight: bold;
}
/* UTILITIES */
.clearfix {
clear: both;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
Start typing a city: <input type="text" name="multiselect" id="input-multicomplete" />
</div>
&#13;