Reputation: 2101
I think that I currently write pretty good javascript, but am trying to move to a more Object Oriented approach. I am just starting with this so forgive my noob-ness. I was moving some of my functions over to objects and ran into this issue. Previously, I had an accordion function that worked like this:
jQuery(document).ready(function ($){
var accordionTrigger = $('.accordion-title');
function toggleAccordion() {
// Set a variable for the accordion content
var accordionContent = $('.accordion-container .accordion-content p');
// Slide up any open content
accordionContent.slideUp();
// Remove any active classes
accordionTrigger.removeClass("active");
// If the sibling content is hidden
if(!$(this).siblings().is(":visible")) {
// slide it down
$(this).siblings().slideDown();
// add a class to the title so we can style the active state and change the svg
$(this).addClass("active");
}
}
accordionTrigger.on("click", toggleAccordion);
});
I have moved this over to an Object in my new set-up like this:
Accordion = {
accordionContent: '.accordion-container .accordion-content p',
accordionTrigger: '.accordion-title',
init: function() {
jQuery(this.accordionTrigger).click(this.toggleAccordion.bind(this));
},
toggleAccordion: function() {
// Slide up any open content
jQuery(this.accordionContent).slideUp();
// Remove any active classes
jQuery(this.accordionTrigger).removeClass("active");
// If the sibling content is hidden
if(!jQuery(this.accordionTrigger).siblings().is(":visible")) {
// slide it down
jQuery(this.accordionTrigger).siblings().slideDown();
// add a class to the title so we can style the active state and change the svg
jQuery(this.accordionTrigger).addClass("active");
}
}
}
jQuery(document).ready(function ($){
Accordion.init();
});
The issue that I'm running into is with the way that 'this' works in Object Oriented Javascript. In the original setup, I was able to use 'this' to reference the accordion content that was clicked. I do not have access to that with the Object Oriented method. Can someone please help me out with?
Upvotes: 3
Views: 262
Reputation: 728
Within toggleAccordion(), you can still use $(this) to get the accordion title element that has been clicked on. Hopefully then you can get the appropriate accordion content.
First bind it like how PHPglue mentioned:
jQuery(this.accordionTrigger).click(this.toggleAccordion);
Then you can do $(this) to get the accordionTitle:
toggleAccordion: function() {
var $accordionTitle = $(this);
}
Basically when you bind it like that and the click is triggered, the scope changes and "this" is no longer "Accordion".
If you need to access accordionContent and accordionTrigger, you can either pass it into the function toggleAccordion or use Accordion.accordionContent and Accordion.accordionTrigger.
Additional source: http://api.jquery.com/click/#click-eventData-handler
Upvotes: 2
Reputation: 1
An alternative approach to @FelixKling solution, removing .bind()
, using event.data
to have access to both jQuery(this)
and Accordion
object within accordionTrigger
handler
var Accordion = {
accordionContent: '.accordion-container .accordion-content p',
accordionTrigger: 'div',
init: function() {
// set `event.data` to `this`:`Accordion` at first parameter to `.click()`
jQuery(this.accordionTrigger).click(this, this.toggleAccordion);
},
toggleAccordion: function(e) {
// Slide up any open content
// jQuery(e.data.accordionContent).slideUp();
// Remove any active classes
// jQuery(e.data.accordionTrigger).removeClass("active");
// If the sibling content is hidden
// `this`:`div`
if (jQuery(this).is(e.data.accordionTrigger)) {
console.log(this, e.data, $(e.data.accordionTrigger))
}
}
}
Accordion.init()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div>
click
</div>
Upvotes: 2
Reputation: 2772
The problem is not how this
works on OOP JavaScript because this
is always referencing the caller object.
You can learn more about this
with You Don't Know JS: this & Object Prototypes.
You can indeed use event.target
and event.currentTarget
as @Felix says, but eventually you will get into trouble if you don't understand how to use this
properly or at least understand how it works.
Upvotes: 2
Reputation: 816442
You can use event.target
to refer to the element that triggered the event, or event.currentTarget
to refer to the element the handler was bound to, which is equivalent to using this
.
toggleAccordion: function(event) {
// Slide up any open content
jQuery(this.accordionContent).slideUp();
// Remove any active classes
jQuery(this.accordionTrigger).removeClass("active");
// If the sibling content is hidden
if(!jQuery(event.currentTarget).siblings().is(":visible")) {
// slide it down
jQuery(event.currentTarget).siblings().slideDown();
// add a class to the title so we can style the active state and change the svg
jQuery(event.currentTarget).addClass("active");
}
}
Learn more about event handling with jQuery.
Upvotes: 7