3

My bloodhound object is reused by two typeaheads, and each typeahead has a hidden image next to it, being these two images: #loading-1 and #loading-2,

    galleriesBloodhound = new Bloodhound({
        datumTokenizer: function (gallery) { return gallery.name; },
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        remote: {
            url: '/GalleriesAjax/List?nameQuery=%QUERY',
            beforeSend: function (xhr) {

            },
            filter: function (response) {
                return response.pageOfGalleries;
            }
        }
    });

Typeahead #1:

    $("#gallery-name").typeahead({
        highlight: false,
        hint: true,
    },
    {
        name: 'galleries',
        displayKey: function (gallery) { return gallery.displayName; },
        source: galleriesBloodhound.ttAdapter()
    }).on(..).on(..)...

Typeahead #2 (same code)

    $("#gallery2-name").typeahead({
        highlight: false,
        hint: true,
    },
    {
        name: 'galleries',
        displayKey: function (gallery) { return gallery.displayName; },
        source: galleriesBloodhound.ttAdapter()
    }).on(..).on(..)...

How can I show the correct #loading-1 and #loading-2 while the ajax request has not returned yet?

In typeahead.js's website they suggested using beforeSend and filter, but "from there" how can I know which typeahead is the one calling the bloodhound?

    beforeSend: function (xhr) {
         $("#loading-i").show();     // How do I figure "i" ??
    },
    filter: function (response) {
        $("#loading-i").hide();     // How do I figure "i" ??
        return response.pageOfGalleries;
    }

    // i depends on the typeahead that is using "this" bloodhound
Fer García
  • 940
  • 1
  • 14
  • 32
sports
  • 7,851
  • 14
  • 72
  • 129
  • if this is not possible, then the idea of separating the engine (bloodhound) from the input (typeahead) is not that good – sports Jun 02 '14 at 01:31
  • I'm facing the exact same problem here. Have you made any progress in solving the problem? Btw, to DRY your code you could initialize the typeahead plugin just one time for both fields, like this: `$(".autocomplete").typeahead({ ... })` (obviously each text field should have the same `autocomplete` class); I'm using three fields that use the same datasource (bloodhound) and that initialization worked just fine. – Fer García Jul 02 '14 at 22:04
  • no progress in solving this... at the end each text field had its own typeahead, bloodhound engine and neighbour-loading-gif – sports Jul 02 '14 at 22:56

3 Answers3

3

Well, I solved our problem (although I'm not 100% happy with this!) with the following assumption: that the focused element should be always the typeahead attached text field.

This is the code (Bloodhound object initialization):

var locsData = new Bloodhound({
  datumTokenizer: Bloodhound.tokenizers.obj.whitespace("name"),
  queryTokenizer: Bloodhound.tokenizers.whitespace,
  remote: {
    url: "/locations/search.json?q=%QUERY",
    ajax: {
      beforeSend: function(xhr, settings) {
        // maybe the 'if' is not necessary, but just to be sure...
        if ($(document.activeElement).typeahead != null) {
          $(document.activeElement).addClass('loading-text');
        }
      },
      complete: function(xhr, status) {
        if ($(document.activeElement).typeahead != null) {
          $(document.activeElement).removeClass('loading-text');
        }
      }
    }
  },
  limit: 100
});

In your case you're toggling the display of some element (a <span>?), in my project I'm adding/removing a class to the element (such class displays a loading.gif inside the right margin of the text field), but the idea should be the same.

For now I will use this in my project. I hope this would also work for you.

Fer García
  • 940
  • 1
  • 14
  • 32
  • I like your solution and the assumption in which its based is quite reasonable, also the "if-is-typeahead" makes the solution more robust, so I would leave it there too. Will try it and see how it goes... – sports Jul 03 '14 at 07:02
1

https://github.com/twitter/typeahead.js

  var data = new Bloodhound({
        datumTokenizer: function (datum) {
            return Bloodhound.tokenizers.whitespace(datum.value);
        },
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        remote: {
            url: "api/lookup/posearch/%QUERY",//,
            prepare: function (query, settings) {
                $("#loadingType").addClass('fa fa-circle-o-notch fa-spin');
                settings.url = "api/lookup/posearch/" + query;
                return settings;
            },               

            filter: function (m) {
                $("#loadingType").removeClass('fa fa-circle-o-notch fa-spin');

                // Map the remote source JSON array to a JavaScript object array
                return $.map(m, function (d) {

                    return {
                        value: d
                    };
                });
            }
        }
    });

    // Initialize the Bloodhound suggestion engine
    data.initialize();
    return data;
katesky8
  • 572
  • 6
  • 9
0

Surely you could use .closest or .next JQuery function to locate the required element.

Dave B
  • 1
  • can you specify how? and closest/next to what? in the bloodhound object I dont have passed references to DOM – sports Jun 23 '14 at 11:32