Question

I have this little class:

var SwitchHider;

SwitchHider = {
  inputSelector: 'body.socials input',
  _showOrHideClosestSwitch: function(element) {
    var socialUrl, swich_wrapper;
    socialUrl = $(element).val();
    swich_wrapper = $(element).closest('.white-box').find('.switch');
    if (socialUrl.length > 0) {
      return swich_wrapper.show();
    } else {
      return swich_wrapper.hide();
    }
  },
  _bindCallbacks: function() {
    $(document).on('ready', function() {
      return $(self.inputSelector).each(function(index, element) {
        return self._showOrHideClosestSwitch(element);
      });
    });
    return $(document).on('change keyup input', self.inputSelector, function() {
      return self._showOrHideClosestSwitch(this);
    });
  },
  initialize: function() {
    var self;
    self = this;
    this._bindCallbacks();
  }
};

window.SwitchHider = SwitchHider;

$(function() {
  SwitchHider.initialize();
});

(it's compiled from this CoffeeScript file, hope it makes sense):

SwitchHider =
  inputSelector: 'body.socials input'

  _showOrHideClosestSwitch: (element) ->
    socialUrl = $(element).val()
    swich_wrapper = $(element).closest('.white-box').find('.switch')
    if socialUrl.length > 0
      swich_wrapper.show()
    else
      swich_wrapper.hide()

  _bindCallbacks: ->
    $(document).on 'ready', ->
      $(self.inputSelector).each (index, element) ->
        self._showOrHideClosestSwitch(element)

    $(document).on 'change keyup input', self.inputSelector, ->
      self._showOrHideClosestSwitch(@)

  initialize: ->
    self = this
    @_bindCallbacks()
    return

# Send to global namespace
window.SwitchHider = SwitchHider

# DOM Ready
$ ->
  SwitchHider.initialize()
  return

And when event is triggered - it gives this error:

TypeError: self._showOrHideClosestSwitch is not a function

Does anyone see why? It's my first attempt to write classes like that, don't fully understand what I'm doing.

Était-ce utile?

La solution

self is not in scope. This is begging for a class syntax:

class SwitchHider
  @inputSelector: 'body.socials input'
  constructor: ->
    $(document).on 'ready', =>
      $(SwitchHider.inputSelector).each (index, element) =>
        @_showOrHideClosestSwitch(element)

    $(document).on 'change keyup input', SwitchHider.inputSelector, (e) =>
      @_showOrHideClosestSwitch(e.target)


  _showOrHideClosestSwitch: (element) ->
    socialUrl = $(element).val()
    swich_wrapper = $(element).closest('.white-box').find('.switch')
    if socialUrl.length > 0
      swich_wrapper.show()
    else
      swich_wrapper.hide()

# Send to global namespace
window.SwitchHider = SwitchHider

# DOM Ready
$ ->
  new SwitchHider()

I used the => to handle proper scope of this

Autres conseils

self is only defined as a local variable under initialize. It won't be available to other methods.

  initialize: function() {
    var self;
    self = this;
    this._bindCallbacks();
  }

You'll either have to define a local self within each method that needs it:

  _showOrHideClosestSwitch: (element) ->
    self = this
    # ...

  _bindCallbacks: ->
    self = this
    # ...

Or, you can use fat arrows to bind each callback to the surrounding context and use this or @ instead:

  _bindCallbacks: ->
    $(document).on 'ready', =>
      $(@inputSelector).each (index, element) =>
        @_showOrHideClosestSwitch(element)

    $(document).on 'change keyup input', self.inputSelector, (ev) =>
      @_showOrHideClosestSwitch(ev.currentTarget)

In the event handler, the Element that's normally the context value can still be retrieved via event.currentTarget.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top