Well, it’s been a busy week. I’ve learned loads, but that’s not exactly new. I’m constantly learning new skills.

A lot of what I learned this week was JavaScript. I’m most proud of my handiwork with a plugin we are using for one of our sites; it’s called Awesomplete. For those who haven’t heard of this plugin, it’s an easily customizable auto-complete for form inputs. You can download it here.

We are using Awesomplete for a search form on the home page. We provide a list of possible values and, when a user starts typing in the form, it provides a list of possible values based on what the user has typed. We wanted the form to have a very specific user experience:

  1. User arrives on homepage
  2. User sees quick search box
  3. User types in city
  4. If city is found, user must select the option from the drop down. If they click out of this, their text is removed from the box as if they made no selection
  5. If no option is found for what they type in, the submit button will never appear . It should only appear when they select an option from the dropdown menu
  6. Once an option is selected in the drop down, the “submit” button appears so they can carry on

As I approached this problem, I attempted to use standard javascript events. For example, I tried to watch all of the <li> elements in my awesomplete list for a click event, like so:

$(‘.awesomplete li’).on(‘click’, function() {});

Unfortunately, this event never fired, and I could not understand why. I approached my project manager for a bit of help and he pointed me to the Awesomplete event docs.

I didn’t even realize that Awesomplete came with custom events. Anyway, to achieve the user experience we wanted, I realized I would be able to use a combination of the events awesomeplete-selectcomplete and awesomplete-close.

The first step I took after this was to add a CSS class to our search button to hide it as a default. I called the class hide-button (genius, I know). I was able to use the -selectcomplete event to verify that the user had clicked on one of the list items, so my event looked like this:

$(‘input.awesomplete’).on(‘awesomplete-selectcomplete’, function(){});

Once I was accurately targeting the event, all I needed to do was remove the hide-button class from my form’s button with a simple (‘#myButton’).removeClass(‘.hide-button’);

So, if a user selected a value from the drop down menu, the submit button would now appear and allow them to continue on with their search. The only thing left to do was make sure that if the user clicked out of the drop down menu, all input would be removed. This is where the event awesomplete-close came in.

I noticed in the docs that when this event fired off, something called a reason was sent with the event object. I wanted to test which reasons I would need for my user experience, so I wrote a really quick test:

$(‘input.awesomplete’).on(‘awesomplete-close’, function(e){

       console.log(e);

}

This allowed me to print out the event as I closed the menu each time.

I noticed in the structure of the event object something called originalEvent, so I opened it up to check it out. Lo and behold, I found what I wanted.

Inside the originalEvent object, I found the reason property. I found two reasons that I wanted to use: blur and esc. The blur reason was sent when I clicked outside of the drop down menu, and the esc reason was sent when I pressed esc while the drop down menu was open.

According to my user experience, I would need to hide the submit button and delete any input if either of those things happened, so I wrote up a function to do just that:

$(‘input.awesomplete’).on(‘awesomplete-close’, function(e){

      if(e.originalEvent.reason == ‘blur’ || e.originalEvent.reason == ‘esc’) {

            $(‘#myButton’).addClass(‘hide-button’);

            $(this).val(‘’);

      }

});

Now I had most of my user experience completed, but I noticed that even if my submit button was hidden, I was able to press enter and the form would still submit. This was an issue. Luckily, it wasn’t too difficult to take care of.

All I needed to do was prevent the default action if the enter button was pressed and the submit button was hidden. I was easily able to figure out the keycode for the enter button (it’s 13). My function looked like this:

$(document).ready(function() {

      var submitButton = $(‘#myButton’);

      $(window).keydown(function(e) {

            if(e.keyCode == 13 && submitButton.hasClass(‘hide-button’)){

                  e.preventDefault();

                  return false;

            }

      });

});

I was finally satisfied with the results of my labors, so I went to my project manager to show him what I’d done and verify that the user experience was exactly what we wanted. He played around with it for a bit, and quickly found something I had missed. (Yay testing!)

He found that if he selected an item from the dropdown menu, then deleted it and typed something else, he was able to proceed with his search. We didn’t want that for our user experience, so I took a few minutes and tried to figure it out.

My first thought was to create a variable to store the value of the text input as soon as it had been selected from the dropdown menu, and then if the text input’s value was different from the variable’s value, I would remove the button.

So, I created a variable whose scope was global to my JavaScript on that page called inputVal. I set the value inside the function with .on(‘awesomplete-selectcomplete’), so the function ended up looking like this:

$(‘input.awesomplete’).on(‘awesomplete-selectcomplete’, function() {

      inputVal = $(this).val();

      $(‘#myButton’).removeClass(‘hide-button’);

});

I also console logged inputVal right there to verify that it was being set the way I wanted.

Once I was certain that inputVal was being set to what I wanted it to be, I had to make another function that would fire off if the value of my text input changed. Being the naive young developer I am, I thought I’d be able to use .on(‘change’) as the event. It makes sense, right?

I was unaware that the change event didn’t actually fire at all for text inputs. I looked up a list of all the events I had available to me, and eventually arrived on the .on(‘input’) event, which does fire when a text input is changed. I wrote up a quick function to do what I needed:

$(‘input.awesomplete’).on(‘input’, function() {

      if(inputVal != $(this).val()) {

            $(‘#myButton’).addClass(‘hide-button’);

      }

});

Finally, my job was complete. I had arrived at the user experience we desired, so I submitted my changes on version control and waited for the good news.

Working with JavaScript is incredibly satisfying for me. Maybe it’s because I know next-to-nothing about it, and anytime I’m able to complete something using JavaScript, I feel very accomplished. Regardless, I was satisfied with myself. A job well done.

Got a question for Zach? Leave it in the comments!