0

I was refactoring my code (I think refactoring is the right word), so I used a function so I wouldn't repeat myself so much. But I think the function messed up my $(this).

The part of my code thats commented out works

I think my problem is in the function at disabled = this;

var active = '.teachers';
var disabled = '.teacher-link';
var width = $('.teachers .staff-outer-container').children().size() * 180;
$('.staff-outer-container').css('width', width + 'px');

/* BELOW IS COMMENTED OUT
$('.teacher-link').click(function() {
    if (active != '.teachers') {
        $(active).hide();
        active = '.teachers';
        $(active).show();
        width = $('.teachers .staff-outer-container').children().size() * 180;
        $('.teachers .staff-outer-container').css('width', width + 'px');
        $(disabled).removeClass('active').addClass('clickable');
        disabled = this;
        $(disabled).removeClass('clickable').addClass('active');
        $('#type').text('Teachers');
    }
});
$('.admin-link').click(function() {
    if (active != '.administrators') {
        $(active).hide();
        active = '.administrators';
        $(active).show();
        width = $('.administrators .staff-outer-container').children().size() * 180;
        $('.administrators .staff-outer-container').css('width', width + 'px');
        $(disabled).removeClass('active').addClass('clickable');
        disabled = this;
        $(disabled).removeClass('clickable').addClass('active');
        $('#type').text('Administrators');
    }
});
$('.support-link').click(function() {
    if (active != '.support') {
        $(active).hide();
        active = '.support';
        $(active).show();
        width = $('.support .staff-outer-container').children().size() * 180;
        $('.support .staff-outer-container').css('width', width + 'px');
        $(disabled).removeClass('active').addClass('clickable');
        disabled = this;
        $(disabled).removeClass('clickable').addClass('active');
        $('#type').text('Support Staff');
    }
});
END COMMENT */

$('.teacher-link').click(function(){handle_click('.teachers','Teachers');});
$('.admin-link').click(function(){handle_click('.administrators','Administrators');});
$('.support-link').click(function(){handle_click('.support','Support Staff');});

function handle_click(target, target_text) {
    if (active != target) {
        $(active).hide();
        active = target;
        $(active).show();
        width = $(target + ' .staff-outer-container').children().size() * 180;
        $(target + ' .staff-outer-container').css('width', width + 'px');
        $(disabled).removeClass('active').addClass('clickable');
        disabled = this;
        $(disabled).removeClass('clickable').addClass('active');
        $('#type').text(target_text);
    }
}

http://jsfiddle.net/X6AbR/

As you can see from my fiddle, the links dont turn grey after clicking. But if I remove the function and uncomment the script, they work again.

Brett Merrifield
  • 2,220
  • 6
  • 22
  • 21

3 Answers3

3

this is set based on how you call the function.

When you call a normal function like handle_click(...), this becomes the global object.
You can call the function with a different this by calling call:

handle_click.call(customThis, arg1, arg2, ...);

Alternatively, you could pass this as a normal parameter and use that parameter instead of this inside the function.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
1

You need this DEMO

The problem is when you register a handler the handler gets the the element on which user clciked as a this ... but when you call handle_click this becomes window object.

So solution is pass this as a parameter to handle_click

$('.teacher-link').click(function(){handle_click('.teachers','Teachers', this);}); // pass this  as a parameter... 

$('.admin-link').click(function(){handle_click('.administrators','Administrators', this);});
$('.support-link').click(function(){handle_click('.support','Support Staff', this);});

function handle_click(target, target_text, clickedElement) {
    if (active != target) {
        $(active).hide();
        active = target;
        $(active).show();
        width = $(target + ' .staff-outer-container').children().size() * 180;
        $(target + ' .staff-outer-container').css('width', width + 'px');
        $(disabled).removeClass('active').addClass('clickable');
        disabled = clickedElement;
        $(disabled).removeClass('clickable').addClass('active');
        $('#type').text(target_text);
    }
}
rahul maindargi
  • 5,359
  • 2
  • 16
  • 23
0

I would have had handleClick return a function specific to that handler: http://jsfiddle.net/X6AbR/1/

$('.teacher-link').click(createClickHandler('.teachers','Teachers'));
$('.admin-link').click(createClickHandler('.administrators','Administrators'));
$('.support-link').click(createClickHandler('.support','Support Staff'));

function createClickHandler(target, target_text) {
    return function (e) {
        e.preventDefault();
        if (active != target) {
            $(active).hide();
            ...

Though I'd probably instead store target and target_text, and the active/disabled in the DOM in the form of classNames and/or data attributes rather than passing them around, such as this answer to your previous question: https://stackoverflow.com/a/16858484/400654. It'd be far more maintainable if you could just add another element in the DOM and your javascript automatically adapt to it.

Community
  • 1
  • 1
Kevin B
  • 94,570
  • 16
  • 163
  • 180