admin管理员组文章数量:1327661
In a nutshell, jQuery-ui autoplete has a 'focus' event (really a hover event) that fires when a user hovers over an autoplete menu choice. But there's no equivalent to get rid of the effects if user continues to type without making a selection.
Here's a fiddle , if that helps.
Question edited to give short version of solution set forth in full below (and in fiddle below)
This solution reverses the focus function, whenever a user moves out of the menu (by mouse or keyboard), and also reverses whenever user first makes a selection then alters the input field.
$( "#id-input" ).autoplete({
.....
focus: function( event, ui ) {
.... do foo ......
$('li.special-class').one ("mouseleave", function() {
.... undo foo .....
});
},
select: function( event, ui ) {
$('li.special-class').off("mouseleave");
.... do foo ....
$( "#id-input" ).one ("keypress", function (e) {
if (e.keyCode !== 13) {
// Keyboard select is ignored, otherwise messing with input undoes foo
.... undo foo ....
}
else {
$( "#id-input" ).one ("keypress", function (e) {
// Re-establish key binding if original select was keyboard
if (e.keyCode !== 13) {
.... undo foo ....
}
})
}
})
}
});
// override the built-in _renderItem to put a special class in all menu items
$( "#id_input" ).data("uiAutoplete")._renderItem = function( ul, item ) {
return $( "<li class='special-class'></li>" )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
};
// override the built-in _move function for keyboard up/down that leaves the menu
$( "#id_input" ).data( "uiAutoplete" )._move = function( direction, event ) {
if ( !this.menu.element.is( ":visible" ) ) {
this.search( null, event );
return;
}
if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
this.menu.isLastItem() && /^next/.test( direction ) ) {
this._value( this.term );
.... undo foo ....
return;
}
this.menu[ direction ]( event );
};
In a nutshell, jQuery-ui autoplete has a 'focus' event (really a hover event) that fires when a user hovers over an autoplete menu choice. But there's no equivalent to get rid of the effects if user continues to type without making a selection.
Here's a fiddle , if that helps.
Question edited to give short version of solution set forth in full below (and in fiddle below)
This solution reverses the focus function, whenever a user moves out of the menu (by mouse or keyboard), and also reverses whenever user first makes a selection then alters the input field.
$( "#id-input" ).autoplete({
.....
focus: function( event, ui ) {
.... do foo ......
$('li.special-class').one ("mouseleave", function() {
.... undo foo .....
});
},
select: function( event, ui ) {
$('li.special-class').off("mouseleave");
.... do foo ....
$( "#id-input" ).one ("keypress", function (e) {
if (e.keyCode !== 13) {
// Keyboard select is ignored, otherwise messing with input undoes foo
.... undo foo ....
}
else {
$( "#id-input" ).one ("keypress", function (e) {
// Re-establish key binding if original select was keyboard
if (e.keyCode !== 13) {
.... undo foo ....
}
})
}
})
}
});
// override the built-in _renderItem to put a special class in all menu items
$( "#id_input" ).data("uiAutoplete")._renderItem = function( ul, item ) {
return $( "<li class='special-class'></li>" )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
};
// override the built-in _move function for keyboard up/down that leaves the menu
$( "#id_input" ).data( "uiAutoplete" )._move = function( direction, event ) {
if ( !this.menu.element.is( ":visible" ) ) {
this.search( null, event );
return;
}
if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
this.menu.isLastItem() && /^next/.test( direction ) ) {
this._value( this.term );
.... undo foo ....
return;
}
this.menu[ direction ]( event );
};
Share
Improve this question
edited Feb 16, 2013 at 7:34
neil.millikin
asked Feb 7, 2013 at 23:47
neil.millikinneil.millikin
1,0771 gold badge10 silver badges15 bronze badges
2
-
Is disabling the
focus
functionality altogether an option? – Andrew Whitaker Commented Feb 8, 2013 at 1:59 - I think I can achieve the correct results using the _renderItem override as @John suggested. What I'm looking for is visual clues to the other values, and it looks like a custom item presentation sounds like the proper way to go. Tunnel vision had me clinging to an outdated method..... << sighs heaviy >> – neil.millikin Commented Feb 8, 2013 at 6:35
3 Answers
Reset to default 3Here's a fiddle for the solution.
code at the bottom
http://jsfiddle/R68jf/5/
Thanks to Capt. Marco Ramius of the Red October for making me realize the way to solve the original posted problem. "One Ping Only".... as explained below.
This http://jsfiddle/R68jf/5/ fiddle presents a working solution, and demonstrates some useful customization to the ui-autoplete widget that may help solve other problems as well. Specifically the solution meets these requirements:
1) Whenever a user navigates over a autoplete menu item, either with a mouse or by keyboard, the 'focus' callback is triggered, which in this case displays additional information and a linked image. This is normal autoplete behavior, exposed in the API and documented.
2) Whenever a user navigates AWAY from or OUT of the menu, the effects of the 'focus' callback should be reversible. This is NOT the default behavior, and there is currently no 'blur' API presented to undo the side effects of 'focus'. Thus, 'zombie' images remain, though the menu item is no longer in focus. The original question fiddle shows this default and the associated 'zombie' effect. To see it, simply type 'spam' and then scroll up and down in the menu. As you scroll, the side effects are updated. Now mouse away from the menu and...... the zombies stay!!
3) If a user makes a selection, using either a mouse click, or return key over a focused item, the side effects associated with that item's focus should persist. This is easy, by using the 'select' method exposed in the documented API.
4) If, after making a menu selection, the user goes back to the search input and changes the search, the side effects should be reversed. This does not happen by default, but instead we have zombies!
To achieve these requirements, I wound up employing the following methods. To the more advanced among us, these may seem elementary, but to others of my pay-grade, this may be a helpful demonstration of ui-autoplete customization:
1) Override the _renderItem method of autoplete to customize the menu presentation.
2) Override the _move method to change behavior when using a keyboard to navigate away from the menu.
3) Use some 'Red October' inspired 'One Ping Only' callbacks, to reverse focus side effects, then return the system to it's original ready state. This uses the jQuery .one() method.
The code here is heavily mented, but a couple of things are worthy of mention:
1) Some events, like selecting an item from the menu and then subsequent closing of the menu, will automatically trigger blur and mouseout events on the menu, as part of their natural behavior. This can be a problem, because, in the current example, I wanted to have a 'blur' function to kill all the zombies, but when an item is selected, that same blur function would kill the legitimate data that I wanted to persist. GRRRRRR!!!
2) When you do $('#mySelector').autoplete({blah:blah, blah:blah}) what happens is that an object is created, of the ui.autopete() class, called 'uiAutoplete' and that object is stored as data within your $('#mySelector') element. So, to access data, options, methods, etc. from the autoplete class, you simply look in $('#mySelector').data() and there it all is!
This is pretty nifty, because it means that things like $('#mySelector').data('uiAutoplete') will get you the whole enchilada, and if you want to override any autoplete function, you can do it by calling $('#mySelector').data('uiAutoplete').myFavoriteFunction = function (){... do nifty stuff ..}.
You don't need to worry about prototypes, or subclassing, or whatever. A good way to play with this is to copy the exact function from the ui-autoplete source code, then paste it onto your instance, and then have at it. You can't break anything because you didn't change the original source (class) code, you simply are changing the code for your instance. Fun, eh?
3) When you do $('#mySelector').autoplete({ foo: function (event, ui) {.. do stuff here..} you can pretty much invent any function you want this way, and then call it by doing this._trigger('foo', event).
This means that the 'official' methods of 'close', 'open', 'focus', 'select', etc. are just 'serving suggestions' and you can write your own functions if you want with no special magic needed to implement them. Your special function can sit as a 'first class citizen' right next to the official ones, and nobody will know the difference. The only difference is that the 'built-in' functions are called my the source code, and you will have to call your functions manually. You can call them from anywhere in your code, because they are accessible through $('#mySelector').data('uiAutoplete').myFunctionName()
4) Additionally, objects like 'ui-menu' and 'uiAutopetemenuItem' are stored as data within their respective objects. In the usual event, these objects don't exist when the page first loaded, but you can use on() to bind an event to future created objects. For example, this will bind a mouseenter event to all future created 'li.spam' objects, and cause them to turn red on mouseover, additionally taking a value from the object's .data() dictionary and assigning it to $('#mySelector'). :
$('body').on( {
mouseenter: function() {
$(this).children('a').css("color", "red");
var currentItem = $(this).data('uiAutopleteItem');
$('#mySelector').value(currentItem.someValue);
}
}, "li.spam");
Code for the whole enchilada (self-contained, apologies if too heavily mented):
<!DOCTYPE html>
<head>
<script src="//ajax.googleapis./ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="//ajax.googleapis./ajax/libs/jqueryui/1.10.0/jquery-ui.min.js"></script>
<link rel="stylesheet" href="http://ajax.googleapis./ajax/libs/jqueryui/1/themes/smoothness/jquery-ui.css" type="text/css" />
<title>fiddle</title>
<script>
(function ($) {
var quoteList = [
{ 'id': "1",
'label': "We're here to preserve democracy.",
'value': "We're here to preserve democracy, not practice it.",
'description': "Capt. Ramsey to Lt. Commander Hunter",
'title': "Gene Hackman as Capt. Ramsey, Denzel Washington as Lt. Cmdr. Hunter",
'stub' : "Crimson Tide",
'image': "http://2.bp.blogspot./_nY72TdvmuKk/S0aoHWh0LeI/AAAAAAAABjY/Yu4krTxxboM/s400/crimsontide.jpg"
},
{ 'id': "2",
'label': "Well, don't like [that cigar] too much.",
'value': "Capt. Ramsey: How do you like that cigar? Hunter: It's good, sir. Capt. Ramsey: It's your first? Hunter: [coughing] Yeah. Capt. Ramsey: Well, don't like it too much. They're more expensive than drugs. ",
'description': "Capt. Ramsey to Lt. Commander Hunter",
'title': "Gene Hackman as Capt. Ramsey, Denzel Washington as Lt. Cmdr. Hunter",
'stub' : "Crimson Tide",
'image': "http://www.vimbly./blog/wp-content/uploads/2012/11/26-e1352860345409.jpg"
},
{ 'id': "3",
'label': "I expect and demand your very best.",
'value': "I expect and demand your very best. Anything less, you should have joined the Air Force.",
'description': "Ramsey to the crew of the Crimson Tide",
'title': "Gene Hackman as Capt. Ramsey, Denzel Washington as Lt. Cmdr. Hunter",
'stub' : "Crimson Tide",
'image': "http://i2.cdnds/12/34/618x405/movies_tony_scott_films_8.jpg"
},
{ 'id': "4",
'label': "The Kirby Silver Surfer is the only true Silver Surfer.",
'value': "Everybody knows that the Kirby Silver Surfer is the only true Silver Surfer.",
'description': "Hunter to Petty Officer First Class Danny Rivetti (Danny Nucci)",
'title': "Gene Hackman as Capt. Ramsey, Denzel Washington as Lt. Cmdr. Hunter",
'stub' : "Crimson Tide",
'image': "http://www.empireonline./images/features/a-z/quentin-tarantino/4.jpg"
},
{ 'id': "5",
'label': "I don't trust air I can't see.",
'value': "I don't trust air I can't see.",
'description': "Ramsey to Hunter",
'title': "Gene Hackman as Capt. Ramsey, Denzel Washington as Lt. Cmdr. Hunter",
'stub' : "Crimson Tide",
'image': "http://images3.cinema.de/imedia/1853/2211853,JSg9qf_ICg9XI70_mnk+0YKnEwjDCNvEJ135zZiOOG51Em+3vDb9zfon3uv_jNxJfz3ogxTr3jHE26akqhRXcA==.jpg"
},
{ 'id': "6",
'label': "Mr Hunter. I've made a decision.",
'value': "Mr Hunter. I've made a decision. I'm Captain of this boat. NOW SHUT THE FUCK UP!",
'description': "Ramsey to Hunter",
'title': "Gene Hackman as Capt. Ramsey, Denzel Washington as Lt. Cmdr. Hunter",
'stub' : "Crimson Tide",
'image': "http://images.static-bluray./reviews/271_1.jpg"
},
{ 'id': "7",
'label': "Mr. Vossler, this is Captain Kirk!",
'value': "Mr. Vossler, this is Captain Kirk! I need warp speed on that munications unit!",
'description': "Hunter to Petty Officer Third Class Russell Vossler (Lillo Brancato)",
'title': "Gene Hackman as Capt. Ramsey, Denzel Washington as Lt. Cmdr. Hunter",
'stub' : "Crimson Tide",
'image': "http://www.livedash./thumb_v5/20091130/crimson%20tide-2009-11-30-0/2_crimson%20tide-2009-11-30-0.jpg"
},
{ 'id': "8",
'label': "I will marry a round American woman and raise rabbits.",
'value': "I will live in Montana. And I will marry a round American woman and raise rabbits, and she will cook them for me. And I will have a pickup truck... maybe even a recreational vehicle. And drive from state to state. Do they let you do that? ",
'description': "Capt. Vasili Borodin (Sam Neill) to Ramius",
'title': "Sean Connery as Capt. Ramius, Alec Baldwin as Jack Ryan",
'stub' : "Crimson Tide",
'image': "http://1.bp.blogspot./-08wMMkx53XQ/TrNoK0ykLzI/AAAAAAAAkK0/p5Q_F6EOrvI/s360/Crimson-Tide.jpg"
},
{ 'id': "9",
'label': "We will lay off their largest city, and listen to their rock and roll!",
'value': "We will pass through the American patrols, past their sonar nets, and lay off their largest city, and listen to their rock and roll... while we conduct missile drills.",
'description': "Ramius to the crew of the The Hunt for Red October",
'title': "Sean Connery as Capt. Ramius, Alec Baldwin as Jack Ryan",
'stub' : "The Hunt for Red October",
'image': "http://lib/files/images/library/alec_baldwin1%5B1%5D.jpg"
},
{ 'id': "10",
'label': "You're afraid. Well, you should be. Personally, I'd give us one chance in three. More tea anyone?",
'value': "You're afraid of our fleet. Well, you should be. Personally, I'd give us one chance in three. More tea anyone? ",
'description': "Ramius to the officers of the The Hunt for Red October",
'title': "Sean Connery as Capt. Ramius, Alec Baldwin as Jack Ryan",
'stub' : "The Hunt for Red October",
'image': "http://i77.photobucket./albums/j60/bluinkalchemist/hunt-for-red-october_480_poster.jpg"
},
{ 'id': "11",
'label': "Hey, Ryan, be careful what you shoot at. Most things in here don't react too well to bullets.",
'value': "Hey, Ryan, be careful what you shoot at. Most things in here don't react too well to bullets.",
'description': "Ramius to Ryan",
'title': "Sean Connery as Capt. Ramius, Alec Baldwin as Jack Ryan",
'stub' : "The Hunt for Red October",
'image': "http://wodumedia./wp-content/uploads/2012/10/Sean-Connery-and-Alec-Baldwin-in-Paramounts-The-Hunt-For-Red-October-1990-0.jpg"
},
{ 'id': "12",
'label': "When he reached the New World, Cortez burned his ships. As a result his men were well motivated.",
'value': "When he reached the New World, Cortez burned his ships. As a result his men were well motivated.",
'description': "Remius to the officers of the The Hunt for Red October",
'title': "Sean Connery as Capt. Ramius, Alec Baldwin as Jack Ryan",
'stub' : "The Hunt for Red October",
'image': "http://content.internetvideoarchive./content/photos/070/002974_25.jpg"
},
{ 'id': "13",
'label': "Russians don't take a dump, son, without a plan.",
'value': "'The average Ruskie, son, don't take a dump without a plan.' Wait a minute. We don't have to figure out how to get the crew off the sub. He's already done that, he would have had to. All we gotta do is figure out what he's gonna do. So how's he gonna get the crew of the sub. ",
'description': "Ryan reliving a ment by Admiral Josh Painter (Fred Thompson)",
'title': "Sean Connery as Capt. Ramius, Alec Baldwin as Jack Ryan",
'stub' : "The Hunt for Red October",
'image': "http://toddmpost.files.wordpress./2010/12/admiralpainter.jpg?w=640"
},
{ 'id': "14",
'label': "At that speed, they could run right over my daughter's stereo and not hear it.",
'value': "They're pinging away with their active sonar like they're looking for something, but nobody's listening... they're moving at almost forty knots. At that speed, they could run right over my daughter's stereo and not hear it.",
'description': "Capt. Davenport (Daniel Davis) to Ryan",
'title': "Sean Connery as Capt. Ramius, Alec Baldwin as Jack Ryan",
'stub' : "The Hunt for Red October",
'image': "http://lib/files/images/library/alec_baldwin1%5B1%5D.jpg"
},
{ 'id': "15",
'label': "I would like to have seen Montana.",
'value': "I would like to have seen Montana.",
'description': "Capt. Vasili Borodin (Sam Neill) to Capt. Ramius",
'title': "Sean Connery as Capt. Ramius, Alec Baldwin as Jack Ryan",
'stub' : "The Hunt for Red October",
'image': "http://img.geocaching./track/display/ad4047d5-a1f9-4a39-86c9-8a7a0873f1ef.jpg"
},
{ 'id': "16",
'label': "Next time, Jack, write a goddamn memo.",
'value': "Next time, Jack, write a goddamn memo.",
'description': "Ryan (talking to himself)",
'title': "Sean Connery as Capt. Ramius, Alec Baldwin as Jack Ryan",
'stub' : "The Hunt for Red October",
'image': "http://www.wearysloth./Gallery/ActorsB/860-9042.gif"
},
{ 'id': "17",
'label': "Give me a ping, Vasili. One ping only, please.",
'value': "Re-verify our range to target... one ping only. Give me a ping, Vasili. One ping only, please.",
'description': "Ramius to Capt. Vasili Borodin (Sam Neill)",
'title': "Sean Connery as Capt. Ramius, Alec Baldwin as Jack Ryan",
'stub' : "The Hunt for Red October",
'image': "http://25.media.tumblr./tumblr_ma1prrCDn81qkcj94o1_1280.jpg"
},
{ 'id': "18",
'label': "Come up right behind his propellor and he'll be deaf as a post!",
'value': "Not if we stay in his baffles, Seaman Beaumont. Not if we stay in his baffles. Come up right behind his propellor and he'll be deaf as a post!",
'description': "Seaman 'Jonesy' Jones (Courtney Vance) to Seaman Beaumont (Ned Vaughn)",
'title': "Sean Connery as Capt. Ramius, Alec Baldwin as Jack Ryan",
'stub' : "The Hunt for Red October",
'image': "http://cdn3.hark./images/000/375/672/375672/original.jpg"
},
{ 'id': "19",
'label': "Andrei, you've lost another submarine?",
'value': "One of our submarines, an Alfa, was last reported in the area of the Grand Banks. We have not heard from her for some time..... Andrei, you've lost another submarine?",
'description': "Dr. Jeffrey Pelt (Richard Jordan) to Russian Ambassador Andrei Lysenko (Joss Ackland)",
'title': "Sean Connery as Capt. Ramius, Alec Baldwin as Jack Ryan",
'stub' : "The Hunt for Red October",
'image': "http://www.wearysloth./Gallery/ActorsJ/8969-9042.gif"
}
];
$(document).ready (function () {
$( "#id_quote" ).autoplete({
minLength: 2,
delay: 2,
source: quoteList,
open: function(event, ui) {
// defines the character of the ui-menu
$(".ui-autoplete")
.css("width", "300px")
.css("max-height", "200px")
.css("overflow-y", "scroll")
},
focus: function( event, ui ) {
// This causes ancillary fields to populate whenever a menu choice is hovered
// also works if menu choices are navigated with keyboard up and down arrows
$( "#id_stub" ).val( ui.item.stub );
$( "#id_title" ).val( ui.item.title );
$( "#id_description" ).val( ui.item.description );
$( "#id_dialog" ).val( ui.item.value );
$( '#id_image').html("<img style='width:100%; height:100%;' src='" + ui.item.image + "' />");
// Ensures that when mouse leaves the manu, that the ancillary fields are emptied
// This is a 'one ping only' event, because 'mouseout' is triggered by the closing of the
// menu when a true choice is made (either by mouse click or return key).
// Making this 'one ping only' ensures that the ancillary fields don't empty
// when the menu closes after a valid selection is made.
// Of course, if there is a new focus, the 'one ping only' rule must be re-established,
// so it is put here, in the focus callback:
$('li.one-ping-only').one ("mouseleave", function() {
$( "#id_stub" ).val("");
$( "#id_title" ).val("");
$( "#id_description" ).val("");
$( "#id_dialog" ).val("");
$( '#id_image').empty();
});
},
select: function( event, ui ) {
// Takes off the 'one ping only' mouse event binding,
// otherwise it would cause the ancillary fields to empty
// due to the 'mouseout' that happens automatically when
// the menu closes.
// In some cases, the mouseout binding has already been removed, but
// in other cases not (by a true mouseout event). This is a safe
// way to make sure before a selection event fills the fields.
$('li.one-ping-only').off("mouseleave");
$( "#id_stub" ).val( ui.item.stub );
$( "#id_title" ).val( ui.item.title );
$( "#id_description" ).val( ui.item.description );
$( "#id_dialog" ).val( ui.item.value );
$( '#id_image').html("<img style='width:100%; height:100%;' src='" + ui.item.image + "' />");
$( "#id_quote" ).val( ui.item.value )
// In general, we want to make sure that if the user goes back and types
// again or backspaces in the autoplete input, AFTER making a selection, then the
// ancillary fields will blank, to avoid zombie data persistence.
// Unfortunately, making a selection with the return key (vs. a mouse click)
// sends (or propagates?) a return key event to the original input field, AFTER the select
// event has been called. Thus, though a valid select event populates the fields (by the
// actions immediately above), the ancillary data is them immediately erased
// by this key event that arrives a split second later.
// To counter this, we make an exception so that in the event that the first key event arriving
// after a select event happens to be a return key, (the selection was made with the keyboard)
// then that single key event is exempted from blanking the field.
.one ("keypress", function (e) {
if (e.keyCode !== 13) {
$( "#id_stub" ).val("");
$( "#id_title" ).val("");
$( "#id_description" ).val("");
$( "#id_dialog" ).val("");
$( '#id_image').empty();
}
else {
// The 'one ping only' event above is REMOVED if any key event takes place, even if it was
// as 'disqualified' return key event. So, even though nothing happened visibly,
// we need to re-establish our 'one ping only' protection from 'real editing' key event.
$( "#id_quote" ).one ("keypress", function (e) {
if (e.keyCode !== 13) {
$( "#id_stub" ).val("");
$( "#id_title" ).val("");
$( "#id_description" ).val("");
$( "#id_dialog" ).val("");
$( '#id_image').empty();
}
})
}
});
}
}).data("uiAutoplete")._renderItem = function( ul, item ) {
// The uiAutoplete object is stored as part data in the input field it is attached to.
// When we call .data("uiAutoplete") here, it relates back to data attribute of the $( "#id_quote" ) that the
// autoplete widget function was attached to. It's helpful to realize that the uiAutoplete object is part of the
// $( "#id_quote" ).data() and can be called at any time, not just here right after autoplete is called.
// This can be confusing, but just remember that once you do $( "#id_quote" ).autoplete({blah blah}), then forever
// .data() attribute of the $( "#id_quote" ) will contain a 'uiAutoplete' object, the properties of which are the
// properties defined in the jQuery-ui class autoplete, as instantiated by you.
// Anyway, we want to override one of the autoplete methods, specifically the _renderItem method
// that makes the items in the menu.
// Here, we specify the nature of the presentation, giving it first the traditional label, and also another line
// that in this case is item.description.
// In addition, we perform a regular expression match on the label, and highlight the letters/words
// that match the search term we have typed into our search input.
var regxpmatch = new RegExp(this.term, "ig");
// Note the 'g' in 'ig' means global to catch any place the letters match, otherwise the default is to match only the first
// instance in any item.label.
// Also note the 'i' in 'ig' makes the match case insensitive.
var formatted_quote = item.label.replace(regxpmatch,"<span style='font-weight:bold;color: red;'>" + this.term + "</span>");
return $( "<li class='one-ping-only'></li>" )
// the 'one-ping-only' class is the hook for our callbacks that erase ancillary fields when a user edits the original
// input after making a selection, and also is used for another callback that erases ancillary fields if the menu loses
// focus by moving the mouse out of the menu, or alternatively using the up or down key on the keyboard to leave
// the menu.
.append( "<a><div class='subquote'>" + formatted_quote + "</div><div class='subtitle'>" + item.description + "</div></a><hr>" )
// makes the menu item have two lines, and puts a horizontal line between each item pair.
.appendTo( ul );
};
$( "#id_quote" ).data( "uiAutoplete" )
._move = function( direction, event ) {
// here we are using a similar logic to override the _move method, ensuring that if the user exits the menu
// using the keyboard, the ancillary fields will clear, just as they do with the 'one ping only' mouseout function
// described above.
if ( !this.menu.element.is( ":visible" ) ) {
this.search( null, event );
return;
}
if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
this.menu.isLastItem() && /^next/.test( direction ) ) {
this._value( this.term );
$( "#id_stub" ).val("");
$( "#id_title" ).val("");
$( "#id_description" ).val("");
$( "#id_dialog" ).val("");
return;
}
this.menu[ direction ]( event );
};
});
})(jQuery);
</script>
<style type="text/css">
div.subquote {font-size: 11px;}
div.subtitle {font-size: 9px; color: blue;}
#id_quote {width: 250px; height:100px;}
#id_stub {width: 250px;}
#id_title, #id_description {width: 250px;}
#id_dialog {width: 250px; min-height: 100px;}
</style>
</head>
<body>
<form action="#" method='POST'>
<div style="float:left; width: 300px;">
<h4>Search submarine movie quotes...</h4>
<h4>...or simply write in your own!</h4>
<div>
<textarea name="quote" type="text" id="id_quote" placeholder="Start typing here...." ></textarea>
</div>
</div>
<div style="float:left; margin-left: 50px;">
<div style="margin: 5px 0 5px 10px;">
<input name="stub" type="text" id="id_stub" />
</div>
<div style="margin: 5px 0 5px 10px;">
<textarea name="title" type="text" id="id_title" ></textarea>
</div>
<div style="margin: 5px 0 5px 10px;">
<textarea name="description" type="text" id="id_description"></textarea>
</div>
<div style="margin: 5px 0 5px 10px;">
<textarea name="dialog" type="text" id="id_dialog"></textarea>
</div>
<button type="submit" id="id_button">Submit your Favorite!</button>
<div name="image" id="id_image" style="width: 250px; height:250px;">
</div>
</div>
</form>
</body>
In your specific example, you can just listen to "keyup" events on the text input. Every time the event is fired you can inspect the .ui-autoplete element and check the list items that have the "ui-state-active" class. If this is 0, then you know nothing is selected.
http://jsfiddle/UVauY/3/
$("#id_main_course").on('keyup',function(){
if($(".ui-autoplete a.ui-state-active").length === 0){
clearall();
}
});
This works for what you described, but there are some issues. The inputs won't be cleared if the user hovers over an item in the list, then hovers out of that item. This causes the item to be de-selected after about a 1 second delay. If it weren't for this delay, you COULD listen to mouseout events on that item and use the same logic above. But, like you said, there just isn't a nice solution for this outside of modifying the jquery UI source yourself to add the feature.
You could try overriding the _renderItem function, and once you've built up the list item, add a proper hover event for it, with your 'unhover' function.
Might work...
More on renderItem
本文标签:
版权声明:本文标题:javascript - jQuery autocomplete 'focus' event fires, but no reverse equivalent. I hover and leave, but changes 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742227041a2436514.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论