0

Amongst other things, I have read:

but they haven't solved 'this' problem I'm having with a piece of JavaScript.

I have a Section object that gets passed some XML which it uses to populate the section. In the Section object I append a div which has a specified index. The resulting jQuery object is pushed into a sections Array. The following code is from the Section object code:

sections.push($('#section' + p_sectionIndex));
this.showSection = function() {
    this.show();
}
this.hideSection = function() {
    this.hide();
}
sections[sections.length-1].on('show', this.showSection.call(sections[sections.length-1]));
sections[sections.length-1].on('hide', this.hideSection.call(sections[sections.length-1]));

Elsewhere I call sections[index].trigger('hide'); and sections[index].trigger('show');

The first of the links I mentioned above seemed to suggest this in a function depends on HOW it's called and that you could pass a reference to this into the function by using call. I know the showSection and hideSection function ARE being triggered - I just can't get the this in those functions to refer to the jQuery objects in the sections Array.

I have tried multiple variations of the above (excluding the call, using $(this) in the functions, adding the showSection and hideSection functions to the jQuery object - amongst others) but I'm kind of out of ideas.
Any help much appreciated!

Community
  • 1
  • 1
moosefetcher
  • 1,841
  • 2
  • 23
  • 39

2 Answers2

1

this in an event handler is the element node that the event was bound to. If you want a jQuery object wrapping that node, use $(this)

Demo: http://jsfiddle.net/b36M6/

This of course assumes you revert back to the correct way of passing a function to the event binding.

Kevin B
  • 94,570
  • 16
  • 163
  • 180
  • +1 This is correct. I missed that the methods weren't wrapping the DOM element, though that's only part of the problem. – cookie monster Mar 10 '14 at 15:33
  • If you could let me know what is the correct way of passing a function to the event binding, that would be great, thanks. I have tried using $(this) in the functions - it doesn't generate any errors, but it also doesn't show the section. – moosefetcher Mar 10 '14 at 15:53
  • My fiddle shows that, so does coookiemonster's answer. If using the code from my fiddle doesn't work, then the problem is likely somewhere else. – Kevin B Mar 10 '14 at 15:54
  • I guess I don't know what you mean by that set of terms. Do you mean 'don't use an Array for the sections'? – moosefetcher Mar 10 '14 at 15:56
  • No, you can use an array if you wish. It's a bit weird, but it will work. – Kevin B Mar 10 '14 at 15:56
  • OK, so what is it that you mean? I'm keen to learn. I've been looking at .map on the jQuery docs, but not making a great deal of progress. How would YOU 'store' a set of dynamically generated elements for easy, specific reference later? Note, I am not selecting these elements from html - I create them by appending them to the '.container' div and then push them into the 'sections' Array as shown above. – moosefetcher Mar 10 '14 at 16:06
  • I would store them in jQuery object. To add a new element to a jquery object, use `theObj.add(newElement)` – Kevin B Mar 10 '14 at 17:32
  • well, i would actually store an array of dom nodes, and do the event binding when you create the element rather than later on the array. – Kevin B Mar 10 '14 at 17:38
  • The problem is some elements need to trigger events in elements that haven't been created yet so, as it is currently set up, I need to add the events after all the elements are present. But I've figured out what the problem was - Your suggestion made me think there was something fundamental that I was totally misunderstanding (I couldn't understand why a jQuery object stored in an Array wouldn't be treated the same way). Turns out I'd set the opacity to 0. Thanks for the help. – moosefetcher Mar 12 '14 at 09:55
0

When you use .call(), you're invoking the function immediately.

Since you want this to refer to the element, bound, just pas the function itself.

sections[sections.length-1].on('show', this.showSection);
sections[sections.length-1].on('hide', this.hideSection);

Now this in the showSection and hideSection methods will refer to the sections[] member to which it was bound.

I assume "show" and "hide" are some sort of custom events.

cookie monster
  • 10,671
  • 4
  • 31
  • 45
  • Sorry, I should have said - That's what I had originally (and I've just tried it again) and it doesn't work. That's what got me looking more into what 'this' is referring to. Thanks for the reply though. Any other ideas will be well received! – moosefetcher Mar 10 '14 at 15:26
  • I am trying to use the show and hide functions on the jQuery object in the sections Array. – moosefetcher Mar 10 '14 at 15:28
  • @moosefetcher: Not sure what you mean. The `.on()` method will set the value of `this` in whatever function it's given to the element to which it was bound. Should work just fine. – cookie monster Mar 10 '14 at 15:29
  • I have taken out both the .calls and the reference in brackets after them, left everything else the same. It doesn't work. Any clue as to why? – moosefetcher Mar 10 '14 at 15:31
  • @moosefetcher: I missed that your functions were not wrapping the `this` in a jQuery object. The value of `this` is going to be a DOM element, so you'd need `$(this).show();`. I would wonder why you're using an Array for these jQuery objects in the first place. That's not typical, since a jQuery object is an Array-like object anyway. – cookie monster Mar 10 '14 at 15:34