0

I have a working javascript solution for a submenu, where the submenu container is not a child or sibling of the link container. I'm just trying to experiment with the prototype pattern. So I am trying to translate the already working code into a prototype pattern to get a more readable code and I'm currently failing. I get no errors in the console, but the code does not work.

jQuery(document).ready(function ($) {
   function tg_dropdown(element) {
      this.element = element;
      this.mainNavigation = $('#top-menu');
      this.dropdownLink = this.mainNavigation.find('.has_dropdown');
      this.bindEvents();
}

tg_dropdown.prototype.bindEvents = function() {
    var $tg_megamenu__link = $('.tg-megamenu__link'),
        self = this;
    $tg_megamenu__link.mouseenter(function(event) {
        self.showDropdown();
    }).mouseleave(function() {
        setTimeout( function () {
        if ($('#top-menu').find('.has-dropdown:hover').length == 0 && $('#main-header').find('.tg-submenu:hover').length == 0)
         self.hideDropdown();
    }, 50);
    })
};

tg_dropdown.prototype.showDropdown = function () {
    $('body').addClass('test');
};

tg_dropdown.prototype.hideDropdown = function () {
    $('body').removeClass('test');
}
});

I might oversee some fundamental basics of the prototype pattern. Can somebody direct me into the right way to get this thing working?

  • 1
    You haven't created any instance of the `tg_dropdown` class. The `tg_dropdown` function (class constructor) is never called. – Titus Oct 07 '17 at 23:01
  • 1
    You need to call `new tg_dropdown(element)` to get a working instance. – ideaboxer Oct 07 '17 at 23:01
  • Possible duplicate of [How does JavaScript .prototype work?](https://stackoverflow.com/questions/572897/how-does-javascript-prototype-work) – ideaboxer Oct 07 '17 at 23:03
  • Consider moving your `tg_dropdown` code to a separate part of the file (or even better: to a separate file) and below just do `jQuery(document).ready(function ($) { new tg_dropdown() })`. – ideaboxer Oct 07 '17 at 23:06
  • And consider injecting jQuery to avoid accessing global references from within your object's methods: `jQuery(document).ready(function ($) { new tg_dropdown($) })`. And, of course, inject what ever else you need to pass to your constructor. – ideaboxer Oct 07 '17 at 23:09
  • And, particularly if you are familiar with other popular object-oriented languages, consider working with classes which makes your code shorter: [Classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) – ideaboxer Oct 07 '17 at 23:14
  • thanks for the massive help. I got it working now. I might need to understand the use of "this" and some other things but you guys helped me saving hours of time! Thank you so much –  Oct 07 '17 at 23:16

1 Answers1

0

What you are writing is telling JS engine to make a memory space for tg_dropdown function, so it won't invoke the function.

function tg_dropdown(element) {
  this.element = element;
  this.mainNavigation = $('#top-menu');
  this.dropdownLink = this.mainNavigation.find('.has_dropdown');
  this.bindEvents();
}

You can use new to create a tg_dropdown object.

Hope this helps:)