Javascript jQuery自动完成';焦点';事件激发,但没有反向等效。我徘徊着离开,但变化依然存在

Javascript jQuery自动完成';焦点';事件激发,但没有反向等效。我徘徊着离开,但变化依然存在,javascript,jquery,jquery-ui,autocomplete,Javascript,Jquery,Jquery Ui,Autocomplete,简而言之,jQueryUIAutoComplete有一个“焦点”事件(实际上是一个悬停事件),当用户将鼠标悬停在autocomplete菜单选项上时会触发该事件。但是,如果用户继续键入而不进行选择,则无法消除效果 如果有帮助的话,这里有一个答案 问题经过编辑,给出了下面完整阐述的解决方案的简短版本(以及下面的提琴) 每当用户移出菜单(通过鼠标或键盘)时,此解决方案会反转焦点功能,并且每当用户首先进行选择然后更改输入字段时,此解决方案也会反转焦点功能 $(“#id输入”).autocomple

简而言之,jQueryUIAutoComplete有一个“焦点”事件(实际上是一个悬停事件),当用户将鼠标悬停在autocomplete菜单选项上时会触发该事件。但是,如果用户继续键入而不进行选择,则无法消除效果

如果有帮助的话,这里有一个答案


问题经过编辑,给出了下面完整阐述的解决方案的简短版本(以及下面的提琴)

每当用户移出菜单(通过鼠标或键盘)时,此解决方案会反转焦点功能,并且每当用户首先进行选择然后更改输入字段时,此解决方案也会反转焦点功能


$(“#id输入”).autocomplete({
.....
焦点:功能(事件、用户界面){
……多福。。。。。。
$('li.special class').one(“mouseleave”,function(){
…撤消foo。。。。。
});
},
选择:功能(事件、用户界面){
$('li.special class').off(“mouseleave”);
……多福。。。。
$(“#id输入”).1(“按键”,功能(e){
如果(例如,keyCode!==13){
//忽略键盘选择,否则干扰输入将撤消foo
…撤销foo。。。。
}
否则{
$(“#id输入”).1(“按键”,功能(e){
//如果原始选择是键盘,则重新建立键绑定
如果(例如,keyCode!==13){
…撤销foo。。。。
}
})
}
})
}
});
//重写内置的renderItem,在所有菜单项中放置一个特殊类
$(“#id_input”).data(“uiAutocomplete”)。_renderItem=函数(ul,项){
返回$(“
  • ”) .append(“+item.label+”) .附录(ul); }; //覆盖离开菜单的键盘向上/向下的内置移动功能 $(“#id_input”).data(“uiAutocomplete”)。_move=函数(方向、事件){ 如果(!this.menu.element.is(“:visible”)){ this.search(null,事件); 返回; } if(this.menu.isFirstItem()&&/^previous/.test(方向)|| this.menu.isLastItem()&&/^next/.test(方向)){ 此._值(本术语); …撤销foo。。。。 返回; } 此菜单[方向](事件); };
    在您的特定示例中,您可以只听文本输入上的“keyup”事件。每次触发事件时,您都可以检查.ui autocomplete元素,并检查具有“ui状态活动”类的列表项。如果该值为0,则您知道未选择任何内容


    这适用于您描述的内容,但存在一些问题。如果用户将鼠标悬停在列表中的某个项目上,然后将鼠标悬停在该项目之外,则不会清除输入。这会导致项目在大约1秒的延迟后取消选择。如果不是因为这个延迟,您可以监听该项上的mouseout事件,并使用上面相同的逻辑。但是,正如您所说,除了自己修改jquery UI源以添加该功能之外,没有一个很好的解决方案。

    您可以尝试覆盖_renderItem函数,并且在构建列表项后,使用“unhover”函数为其添加适当的悬停事件

    可能有用

    这里有一个例子

    代码在底部

    感谢红色十月号的马尔科·拉米斯上尉让我意识到解决最初问题的方法。“只有一平”。。。。如下所述

    这个fiddle提供了一个有效的解决方案,并演示了一些对ui自动完成小部件的有用定制,这些定制还可以帮助解决其他问题。具体而言,该解决方案满足以下要求:

    1) 每当用户使用鼠标或键盘浏览自动完成菜单项时,就会触发“焦点”回调,在本例中,该回调显示附加信息和链接图像。这是正常的自动完成行为,在API中公开并记录在案

    2) 每当用户离开或离开菜单时,“焦点”回调的效果应该是可逆的。这不是默认行为,并且目前没有提供用于撤消“聚焦”的副作用的“模糊”API。因此,“僵尸”图像仍然存在,尽管菜单项不再聚焦。原始问题小提琴显示了此默认值和相关的“僵尸”效果。要查看它,只需键入“垃圾邮件”,然后在菜单中上下滚动即可。滚动时,副作用会更新。现在鼠标从菜单上移开。。。。。。僵尸们留下来

    3) 如果用户使用鼠标单击或返回键在焦点项目上进行选择,则与该项目焦点相关的副作用应持续存在。这很容易,通过使用文档化API中公开的“选择”方法

    4) 如果在进行菜单选择后,用户返回搜索输入并更改搜索,则副作用应被逆转。这在默认情况下不会发生,但是我们有僵尸

    为了达到这些要求,我最终采用了以下方法。对于我们中更高级的人来说,这些可能看起来很简单,但对于我的其他同龄人来说,这可能是ui自动完成定制的一个有用的演示:

    1) 覆盖自动完成的_renderItem方法以自定义菜单显示

    2) 重写_move方法以更改使用键盘导航离开菜单时的行为

    3) 使用一些受“红色十月”启发的“仅一次Ping”回调,以逆转聚焦副作用,然后将系统恢复到其原始就绪状态。这使用jQuery.one()方法

    这里的代码有很多注释,但有几点值得一提:

    1) 某些事件,如从菜单中选择一个项目,然后关闭菜单,将自动触发菜单上的模糊和鼠标移出事件,作为其自然行为的一部分。这可能是个问题,因为在当前的示例中,我想要一个“模糊”函数来杀死所有的僵尸,b
    $( "#id-input" ).autocomplete({
    .....
    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("uiAutocomplete")._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( "uiAutocomplete" )._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 );
    };
    
    $("#id_main_course").on('keyup',function(){
         if($(".ui-autocomplete a.ui-state-active").length === 0){
             clearall();
         }
    });
    
    $('body').on( {
    mouseenter: function() {
        $(this).children('a').css("color", "red");
        var currentItem = $(this).data('uiAutocompleteItem');
        $('#mySelector').value(currentItem.someValue);
    }
    }, "li.spam");
    
    <!DOCTYPE html>
    <head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.0/jquery-ui.min.js"></script>
    <link rel="stylesheet" href="http://ajax.googleapis.com/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.com/_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.com/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.net/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.com/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.com/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 communications 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.com/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.com/-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://libcom.org/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.com/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.com/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.com/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 comment 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.com/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://libcom.org/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.com/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.com/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.com/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.com/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.com/Gallery/ActorsJ/8969-9042.gif"
          }
     ];
    
    $(document).ready (function () {
    
        $( "#id_quote" ).autocomplete({
            minLength: 2,
            delay: 2,
            source: quoteList,
            open: function(event, ui) {
                // defines the character of the ui-menu
                $(".ui-autocomplete")
                .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 autocomplete 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("uiAutocomplete")._renderItem = function( ul, item ) {
            // The uiAutocomplete object is stored as part data in the input field it is attached to.
            // When we call .data("uiAutocomplete") here, it relates back to data attribute of the $( "#id_quote" ) that the
            // autocomplete widget function was attached to.  It's helpful to realize that the uiAutocomplete object is part of the
            // $( "#id_quote" ).data() and can be called at any time, not just here right after autocomplete is called.
            // This can be confusing, but just remember that once you do $( "#id_quote" ).autocomplete({blah blah}), then forever
            // .data() attribute of the $( "#id_quote" ) will contain a 'uiAutocomplete' object, the properties of which are the
            // properties defined in the jQuery-ui class autocomplete, as instantiated by you.
            // Anyway, we want to override one of the autocomplete 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( "uiAutocomplete" )
        ._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>