1
\$\begingroup\$

I've written a "clever" bit of javascript that sets up typeahead and bloodhound for use as a global search facility.

To make this even more clever, I've stashed a date for when the search JSON that powers bloodhound, into an application variable so that I don't have to keep getting the JSON on each page load, however I have to access this stashed variable somehow. So I've gone and done something like this (using jQuery) and I've truncated it a little as some of the functions are pretty similar:

$(function(){
  var accentedcharmap = {"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"Ae"... etc};

  var normalize = function(str) {
    $.each(accentedcharmap, function(chars, normalized) {
      var regex = new RegExp('[' + chars + ']', 'gi');
      str = str.replace(regex, normalized);
    });

    return str;
  }

  var queryTokenizer = function(q) {
    var normalized = normalize(q);
    return Bloodhound.tokenizers.whitespace(normalized);
  };

  var coreObjects = coreObjects || {};

  coreObjects.methods = {
    dateRefreshed : '',
    jurisdictionsObject : '',
    practiceAreasObject : '',
    contactsObject : '',
    organisationsObject : '',
    organisationsLookup : '',
    contactsLookup : '',
    practiceAreasLookup : '',
    jurisdictionsLookup : '',
    BloodHoundContacts : '',
    BloodHoundOrganisations : '',
    BloodHoundJurisdictions : '',
    BloodHoundPracticeAreas : '',
    setJurisdictions : function(){
      if(this.jurisdictionsObject.length == 0 && typeof(sessionStorage) != 'undefined' && !sessionStorage.getItem('GTDT-coreObjects-Jurisdictions')){
        this.jurisdictionsObject =  $.getJSON(core.appurl + 'app/controllers/concerns/concern.json.data.cfm?sType=jurisdictions')
        .done(function(data){
          if(typeof(sessionStorage) != 'undefined' && !sessionStorage.getItem('GTDT-coreObjects-Jurisdictions')){
            sessionStorage.setItem('GTDT-coreObjects-Jurisdictions', JSON.stringify(data));
          }
          return JSON.stringify(data);
        });
      } else {
        this.jurisdictionsObject = sessionStorage.getItem('GTDT-coreObjects-Jurisdictions');
      }
    },
    JurisdictionsBloodHound : function(){
      var jurisdictionsLookup = {};
      if(this.jurisdictionsObject.length == 0){
        this.BloodHoundJurisdictions = new Bloodhound({
          datumTokenizer: function(data){
            return Bloodhound.tokenizers.whitespace(normalize(data.name));
          },
          queryTokenizer: Bloodhound.tokenizers.whitespace,
          prefetch: {
            url: core.appurl + 'app/controllers/concerns/concern.json.data.cfm?sType=jurisdictions',
            filter: function(parsedResponse){
              return $.map(parsedResponse.DATA.NAME, function (data, index) {
                jurisdictionsLookup[data] = parsedResponse.DATA.ID[index];
                return {
                  name: [data]
                };
              });
            },
            ttl: 0,
            thumbprint: 'jurisdictions'
          },
          limit: 3
        });
      } else {
        var jurisdictionsJSON = JSON.parse(this.jurisdictionsObject);

        this.BloodHoundJurisdictions = new Bloodhound({
          datumTokenizer: function(data){
            return Bloodhound.tokenizers.whitespace(normalize(data.name));
          },
          queryTokenizer: Bloodhound.tokenizers.whitespace,
          local: $.map(jurisdictionsJSON.DATA.NAME, function(data, index){
            jurisdictionsLookup[data] = jurisdictionsJSON.DATA.ID[index];
            return {name: data};
          })
        });
      }
      this.jurisdictionsLookup = jurisdictionsLookup;
    },
    initialize : function(){
      var self = this;

      var finishedInit = $.ajax({
        url: core.appurl + 'app/controllers/concerns/concern.json.data.cfm?sType=refreshdate',
        dataType: 'json'
      }).done(function(data){
        //return data;
        self.dateRefreshed = Date.now();

        var applicationDateRefreshed = data.responseJSON;

        if(applicationDateRefreshed >= self.dateRefreshed || self.jurisdictionsObject.length == 0){
          self.setJurisdictions();
          self.setPracticeAreas();
          self.setContacts();
          self.setOrganisations();
        }
      }).fail(function(){
        self.setJurisdictions();
        self.setPracticeAreas();
        self.setContacts();
        self.setOrganisations();
      }).always(function(){
        self.OrganisationBloodHound();
        self.BloodHoundOrganisations.initialize();
        self.PracticeAreasBloodHound();
        self.BloodHoundPracticeAreas.initialize();
        self.JurisdictionsBloodHound();
        self.BloodHoundJurisdictions.initialize();
        self.ContactsBloodHound();
        self.BloodHoundContacts.initialize();
      });

      return finishedInit;
    }
  }

  var finishedInit = coreObjects.methods.initialize();

  finishedInit.always(function(){
    //setup typeahead
  });
});

So what happens is, on page load:

  1. We init my object, which makes a call to find out when the global search terms were last refreshed.
  2. Assuming that comes back with a 200, we check the response date to see if that is greater than now, we also check to see if there is anything in the jurisdictionsObject.
  3. If either of those are false, we then check to see if the sessionstorage object exists and is blank, if it exists we grab from the sessionstorage, if not we make a JSON call and get the latest JSON. This is actually possibly the wrong thing I want to do...
  4. We then setup the bloodhound objects, either using local data or prefetching the data.
  5. We then return the original daterefreshed JSON call and do an .always to setup the typeahead.

Now I think this is quite clever, but there is a slight issue in that it does a bit of blocking on page load. It's also the first time I've written something like this, so I'm looking for a few pointers on where I might be going wrong.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.