14

I have a customised jQuery autocomplete control that is declared something like this.

$('#SystemCode_Autocomplete').autocomplete({
    source: [{"label":"Access","value":0},{"label":"Documentum","value":0}], //move values
    minLength: 1,
    change: function(event, ui) {// some function},
    select: function(event, ui) {// some function}
});

The change and select events are custom. The problem is if I type something into the textbox then click the submit button (i.e. no tab out, or lost of focus), or if I press the key to submit after typing into the text box, the change event isn't fired and it has to be before I submit.

I was hoping to do it without putting javascript behind the submit button, and to ideally do it from within the autocomplete control itself. I tried adding the change to the blur event.

${'foo').blur(function() { $('bar').trigger('autocompletechange');
// or
${'foo').blur(function() { $('bar').change();

But none of them have worked, anyone have any ideas?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
MrJoeBlow
  • 466
  • 1
  • 5
  • 13

5 Answers5

1

You can try something like this:

$('#SystemCode_Autocomplete').autocomplete({
    source: [{"label":"Access","value":0},{"label":"Documentum","value":0}], //move values
    minLength: 1,
    change: function(event, ui) {/* some function */},
    select: function(event, ui) {/* some function */}
}).each(function(){
    var self = $(this).closest("form").submit(function(e){
        self.trigger("change");

        // you may not need anything like this...but whatever
        if(!functionToCheckIfFormIsValid()){
            e.preventDefault();
        }
    });
});
David Murdoch
  • 87,823
  • 39
  • 148
  • 191
0

focus function autocomplete

Before focus is moved to an item (not selecting), ui.item refers to the focused item. The default action of focus is to replace the text field's value with the value of the focused item, though only if the focus event was triggered by a keyboard interaction. Canceling this event prevents the value from being updated, but does not prevent the menu item from being focused.

Solve the problem:

    $('#SystemCode_Autocomplete').autocomplete({
        source: [{"label":"Access","value":0},{"label":"Documentum","value":0}], //move values
        minLength: 1,
        focus: function( event, ui ) {
            return false;
        },
        select: function(event, ui) {
            alert('Select Event:'+ui.item.value);
        }
    });
user1217167
  • 83
  • 1
  • 5
  • Hi.Thanks for your response. I'll try it but I though focus worked on the "item" being focused not the textbox? – MrJoeBlow Nov 02 '10 at 09:17
  • Yeah that didn't work. The focus event fires when an ui.item is selected. My problem is that if I dont tab out of the texbox (by pressing to submit or clicking the submit button directly) my change and select events dont fire. – MrJoeBlow Nov 02 '10 at 11:27
0

So your problem is that you have to make sure that action a occurs before action b and you're having trouble reconciling that between two event handlers? That actually sounds like a pretty common UI problem, not something that's limited to jQuery.

How would you solve it in any other circumstance? What if I suggested you to use the jQuery data object to attach to the element and then do some sort of semaphore checking in each method, like setting a flag in the one method, and in the other method checking to see if the flag is set?

That's how I would do it, were it me.

jcolebrand
  • 15,889
  • 12
  • 75
  • 121
  • Hi. No my problem is my Change event doesn't fire unless I tag out of the control. I need the change event to fire when I submit the form so it runs its valiation. I could add it to the subbmit button, but I wanted to know if there was a nicer way of doing it. Something about JQuery I didn't know yet for instance. – MrJoeBlow Nov 04 '10 at 08:49
  • No way to force a UI event to fire on a non-UI event boundary. Consider the consequences of causing mouseup to fire every thirty seconds, even if you're holding the mousedown on purpose. – jcolebrand Nov 04 '10 at 13:50
  • @drachenstern your point is right, but a solution exist, test my responce. ;) – Luca Filosofi Nov 05 '10 at 13:22
  • @aSeptik ~ You concede that there is no way to force a UI event to fire off the event boundary, short of manually calling the code, but yet you want me to consider code that does exactly what I maintain? I believe it's possible and know it to be the only solution. My point was that he's going to be forced to call the event handler at some point. That was all. So yes, great, you did what I told him he had to do, but how are you tracking the semantic semaphore? – jcolebrand Nov 05 '10 at 14:18
  • 1
    @drachenstern: lol , i must admit, i have not read your responce, i was referring just to your comment "...Consider the consequences of causing mouseup to fire every thirty seconds..." and one more time i say: you are right; i guess that a mouseup is already firing each time autocomplete widget check typed word against json, so, while doing this, we can do that semaphore you are saying? – Luca Filosofi Nov 05 '10 at 15:13
  • @Takinremi ... we did. I was his +1 there ;) – jcolebrand Nov 07 '10 at 16:32
0
$(function() {
var json = [{"label":"Access","value":0},{"label":"Documentum","value":0}];
$('#SystemCode_Autocomplete').autocomplete({
    source: function( request, responce ) {
        responce( $.map( json, function( item ) {
            return { id: item.value, label: item.label, value: item.label }
        }));
        $.each( json, function( i, item ) {
            if ( request.term.toLowerCase() == item.label.toLowerCase() ) { 
                   // do something here, ex.: AJAX call or form submit...
                $('#submit_button').click();
            }
        });   
    },
    minLength: 1,
    change: function(event, ui) { /*alert(ui.item.label + ' ' + ui.item.id)*/ },
    select: function(event, ui) {}
   });
});
Luca Filosofi
  • 30,905
  • 9
  • 70
  • 77
0

Ok I completely for to update this to what we actually did to get it to work. Basically we editted the autocomplete .js file to get it to do want we wanted. Specifically we added our own options to the autocomplete then we editted the _response method to something like this

_response: function (content) {
        if (content.length) {
            content = this._normalize(content);
            this._suggest(content);
            this._trigger("open");

            this.options.isInError = false;
            this.element.removeClass("input-validation-error");
        } else {
            this.close();

            if (this.element.val() == '') {
                this.options.hiddenField.val('');
            } else {
                this.options.hiddenField.val('-1');
            }
            if (this.options.mustBeInList) {
                this.options.isInError = true;
                this.element.addClass('input-validation-error');
            }
        }
        this.element.removeClass("ui-autocomplete-loading");
    },

That way we know if the User is entering "rubbish" as they type and the controll goes red and into an "error"mode. To stop them from posting back we do this

case keyCode.ENTER:
                case keyCode.NUMPAD_ENTER:
                    // when menu is open or has focus

                    if (self.options.isInError == true) {
                        return false;
                    }

                    if (self.menu.element.is(":visible")) {
                        event.preventDefault();
                    }
                    //passthrough - ENTER and TAB both select the current element
                case keyCode.TAB:
                    if (!self.menu.active) {
                        return;
                    }
                    self.menu.select(event);
                    break;
MrJoeBlow
  • 466
  • 1
  • 5
  • 13