2
\$\begingroup\$

I've been happily using jQuery, creating vars and binding events in my modules (which have only a little bit of JS). But recently I needed to add an anonymous functions to my code and after investigating some more, I learned about modular patterns and encapsulation.

So what I'm trying to teach myself is to write clean, fast and maintainable JavaScript code in object-oriented fashion (as opposed to "functional" jQuery code before).

My module inserts a search box (input) that uses Ajax and displays drop-down results.

What I want to have is a template file with the search box other necessary elements; Then the most flexible way would be to pass the elements to the code in JavaScript file - I could easily adjust settings in the same file if I decide to change IDs or the elements.

Then there should be a separate file with the actual code; It should make no presumptions about the elements of the page.

I follow this article:

http://esbueno.noahstokes.com/post/77292606977/self-executing-anonymous-functions-or-how-to-write

These are my thoughts and what I would like to know:

  • Is this structure written correctly to accomplishing this task?
  • Is the anonymous function (self-executing one) being used correctly here?
  • Is there anything to be optimized (maybe I'm "overkilling" something)?
  • Is $.proxy used correctly?
  • I to use an object to defined methods, however, I cant think of a way to only expose a public method. Is writing non-objective (simple enclosed vars and functions) the way to go?

search_box.tpl

<script type="text/javascript" src="autosearch.js"></script>

<form>
    <input id="search-1" type="search">
</form>

<script type="text/javascript">
    AutoSearch.init({
        input  : $('#search-1'),
        option2: ''
    });
</script>

autosearch.js

var AutoSearch = (function($) {

    var search = {

        cache: {},
        bindEvents: function(){
           this.input.on('keyup', $.proxy(this.processInput, this));
        },
        processInput: function(){ alert(this.input.val()); },

        init: function(options) {
            this.input = options.input;

            this.bindEvents();
        }
    }

    return search;

    })(jQuery);
\$\endgroup\$
  • \$\begingroup\$ I fixed it up a little bit. It has all the relevant parts. Mostly I'm interested in the layout and structure. \$\endgroup\$ – gskema Dec 18 '14 at 21:46
2
\$\begingroup\$

Your mistake is in your processInput() function, it is not created as part of the search object and is invalid syntax the way you have it written.

I try to avoid private functions in javascript as it makes them difficult to test, but if you really wanted to have private functions, you could write your module like this:

var AutoSearch = (function () {
    "use strict";

    // private
    var my = {},
        input;

    // private
    function processInput() {
        alert(input.val());
    }

    // private
    function bindEvents() {
        input.on('keyup', processInput());
    }

    // public
    my.init = function (options) {
        input = options.input;
        bindEvents();
    };

    return my;
}());

It's not obvious to me that you need jQuery or .proxy() at this point, since all the data and functions for the event handler are inside the closure.

\$\endgroup\$
  • \$\begingroup\$ The mistake was just a typo. I followed this example esbueno.noahstokes.com/post/77292606977/… \$\endgroup\$ – gskema Dec 19 '14 at 6:38
  • \$\begingroup\$ That's a good example. Looks like they decided not to hide the functions, which is what I usually prefer. However I feel that avoiding using this (as in my example) makes the code easier to read/understand. \$\endgroup\$ – mikhail Dec 19 '14 at 18:15

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.