5

I just want to fire an event when an input changes value using jQuery 1.7.2 and Backbone.js.

Currently I have the following (which works)

MyView: Backbone.View.extend({
  initialize: function() {

    this.colorInput = $("<input />", {
         "id": "color",
         "name": "color",
         "value": this.model.get("color")
    });

    var self = this;
    this.colorInput.on("change", function() {
      self.changeColor();
    });

  },
  changeColor: function() {
    var color = this.colorInput.val();
    this.model.set("color", color);
  }
});

I was trying to do it the other way where I just pass in my function.

this.colorInput.on("change", this.changeColor, this);

But when trying to do it that way, it throws the error

((jQuery.event.special[handleObj.origType] || {}).handle || handleObj.handler).apply is not a function
.apply( matched.elem, args );

(line 3332)

Which I'm not able to figure out. Any ideas why this way doesn't work?

Brandon
  • 65,640
  • 30
  • 189
  • 218

2 Answers2

11

You're confusing jQuery's on:

.on( events [, selector] [, data], handler(eventObject) )
.on( events-map [, selector] [, data] )

with Backbone's on:

object.on(event, callback, [context])

Backbone's takes a context as the third argument, jQuery's doesn't. Looks like jQuery's on is interpreting your third argument as the handler(eventObject) and trying to call it like a function, that would explain the error message that you're seeing.

Normally you'd do it more like this:

MyView: Backbone.View.extend({
  events: {
    'change input': 'changeColor'
  },
  initialize: function() {
    this.colorInput = $("<input />", {
       "id": "color",
       "name": "color",
       "value": this.model.get("color")
    });
  },
  render: function() {
    this.$el.append(this.colorInput);
    return this;
  },
  changeColor: function() {
    var color = this.colorInput.val();
    this.model.set("color", color);
  }
});

and let Backbone's event delegation system take care of things.

mu is too short
  • 396,305
  • 64
  • 779
  • 743
  • +1, Yes, same opinion here. I'm also having problems to have a working example, the _onlive created_ DOM element is not triggering `change` event, I gave up due it was not a problem related to the question. – fguillen Jun 13 '12 at 22:07
  • 1
    @fguillen: I half-undid the edit, I think `.on` is doing an [`isPlainObject`](http://api.jquery.com/jQuery.isPlainObject/) check on its first argument to choose which form it is using, the first argument isn't an event-map so it goes with the first form of `.on` and we're back trying to call a view object like a function. Are you having the "change isn't triggered until focus changes" problem? – mu is too short Jun 13 '12 at 22:17
  • @muistooshort, this is perfect. Thank you for the explanation and the code sample. This way is much better and it works great. I had to change the events selection to `change #color` to get it working, but other than that it is great. Thanks again. – Brandon Jun 13 '12 at 22:24
  • @fguillen: I had the event spec backwards, `'input change'` should have been (and now is) `'change input'`: http://jsfiddle.net/ambiguous/xD7Xm/ – mu is too short Jun 13 '12 at 22:24
  • @Brandon: I had the event spec backwards (duh!), see my last comment to fguillen. – mu is too short Jun 13 '12 at 22:25
  • @muistooshort you see, I knew I was missing something, just the number of arguments... to easy :P – fguillen Jun 13 '12 at 22:51
  • @muistooshort about the _Are you having the "change isn't triggered until focus changes" problem?_ I didn't know about this issue but it is very probable. In my experiments I was modifying `colorInput.val()` by code and the event was no triggered, like here: http://jsfiddle.net/fguillen/qZ8aN/ – fguillen Jun 13 '12 at 22:55
  • @fguillen: The event isn't triggered until the value changes *and* there is a focus change (more or less): http://stackoverflow.com/a/7055771/479863 – mu is too short Jun 13 '12 at 22:59
  • @muistooshort this HTML specifications were done before JS was implemented :)... I see, if we go with the book the behavior is the proper one, still I have opened a [jQuery bug](http://bugs.jquery.com/ticket/11904) just to make noise about this. – fguillen Jun 13 '12 at 23:11
  • Although your comment didn't directly apply, you did help me out by giving me a clue as to what was happening, so +1 to you. I was trying to call lodash's `debounce()` in a window scroll handler, but I had a typo and was passing the `debounce()`'s params to `on()`'s. – CodeChimp May 24 '16 at 18:18
3

This is for the Googlers who come across this problem. I had this exact same issue and what occurred was that where the error was being reported and where the error actually occurred were in two different places.

One line of code was obsolete and looked something like

$('#modal').on('click', function(e) {
   // Execute invalid code here.
});

The other line of code was similar:

$('#modal').on('click', function(e) {
   // Execute valid code here.
});

The error was that the first invocation was not a true function, so the error was accurate, the second handler being invoked was not a true function and jQuery couldn't complete it, but it always acted as if it occurred on the second function call.

I'd say if you run into this error, remove any extra event handlers that may be triggered and see if that stops the problem.

Michael Ryan Soileau
  • 1,553
  • 14
  • 26