CanVas
@CanVas
Веб-мастер

Как исправить ошибку переопределения this в javascript с jquery?

Есть код:

Formslider.prototype.slidergoto = function (no) {
//....
};
Formslider.prototype.setSlider = function () {
//...
    this.sliderall.find('a.next').click( function(event) {
        this.slidergoto(this.slidercurrent+1);
        return false;
    });
//....
};


this.sliderall - объект. ну я думаю тут так и всё понятно. я пытаюсь вызвать функцию slidergoto(). но к сожалению, jquery переопределяет переменную this. И из за этого функция slidergoto не вызывается если она внутри обработчика .click()

Что делать?

Проблема в том что я пошёл в сторону классов на JS, грубо говоря для того - что бы можно было вызывать одну функцию слайдера для двух и более объектов на странице.

В общем порядок:
Есть в html один див с id=tables. В нём слайдер и форма.
Я запускаю свою функцию "Formslider", передавая в неё соответствующие параметры.
var tables = new Formslider('#tables','.content_tablesprod','.slider','.product','.nav');
        tables.initr();


Функция сначала объявляет параметры по умолчанию:
function Formslider(all,sliderwrap,slidercontainer,slideritems,slidernav) {
console.log('===function Formslider() | start');
            this.all = all;
            this.alll = $(all);
            this.sliderwrap = sliderwrap;
            this.sliderall = $(this.sliderwrap);
            this.slidercontainer = $(slidercontainer);
            this.slideritems = this.slidercontainer.find(slideritems);
            this.slidernavs = this.sliderall.find(slidernav);
            this.sliderdopnav = this.sliderall.find('.dopnav');
            this.sliderdopnav.eq(0).addClass('active');
            this.slidercount = this.slideritems.length;
            this.slidercount0 = this.slidercount-1;
            this.slidercount00 = this.slidercount-2;
            this.slidertarget = 0;
            this.slidertarpos = 0;
            this.slideritemw = this.slideritems.eq(0).width();
            this.slidercurrent = 0;
            this.form = this.sliderall.parent().next();
            this.inputproduct = this.form.find('input.product');
            this.formprev = this.form.find('a.prev');
            this.formnext = this.form.find('a.next');
            this.formsteps = this.form.find('.step');
            this.formstepcurr = 0;
            var tral = ral_html(ral);
            this.form.find('.colorone').find('.colors').html(tral);
            this.form.find('.colortwo').find('.colors').html(tral);
            this.form.find('.steps').find('.step').eq(0).css('display','block');
            this.form.slideUp(10);
console.log('===function Formslider() | end');
        }


После чего в этом классе я вызываю инициализацию.
На этапе инициализации я и объявляю переменную self:
Formslider.prototype.initr = function () {
console.log('===Formsslider.prototype.initr | start');
            var self=this;
console.log('---self=',self);
            this.setSlider();
            this.setform();
console.log('===Formsslider.prototype.initr | end');
        };


Инициализация запускает функции установки слайдера и установки формы. Установка - навешивает обработчики нажатия кнопок навигации слайдера:
Formslider.prototype.setSlider = function () {
console.log('===Formslider.prototype.setSlider | start');

console.log('---self=',self);
            self = this;
console.log('---self=this=',self);
            this.sliderall = $(this.sliderwrap);
            this.sliderall.attr('data-select','0');

            this.sliderall.find('a.next').click( function(event) {
console.log('---self=',self);
console.log('---this=',this);
                self.slidergoto(self.slidercurrent+1);
                return false;
            });
console.log('---self=',self);
console.log('---this=',this);
            this.sliderall.find('a.prev').click( function(event) {
                self.slidergoto(self.slidercurrent-1);
                return false;
            });

            this.slidernavs.click( function(event) {
                if (self.slidernavs.index($(this))!=self.slidercurrent) {
                    self.slidergoto(self.slidernavs.index($(this)));
                }
                return false;
            });

            this.sliderdopnav.click( function(event) {
console.log('---this=',this);
console.log('---$(this)=',$(this));
                switch (self.all) {
                    case '#tables':
                        switch (self.sliderdopnav.index($(this))) {
                            case 2:
                                self.slidergoto(self.slidercount0);
                                break;
                            case 1:
                                self.slidergoto(self.slidercount0-1);
                                break;
                            case 0:
                                self.slidergoto(0);
                                break;
                        }
                        break;
                    case '#disinfecting':
                        switch (self.sliderdopnav.index($(this))) {
                            case 1:
                                self.slidergoto(1);
                                break;
                            case 0:
                                self.slidergoto(0);
                                break;
                        }
                        break;
                }

                return false;
            });

            this.slideritems.eq(this.slidercurrent).addClass('active');
            this.sliderall.attr('data-select',this.slidercurrent);
console.log('===Formslider.prototype.setSlider | end');
        };


Ну и обработчик допустим нажатия кнопки вперёд - вызывает функцию slidergoto:
Formslider.prototype.slidergoto = function (no) {
console.log('===Formslider.prototype.slidergoto | start');
            if (no<0) {
                this.slidertarget = this.slidercount0;
            } else {
                if (no>this.slidercount0){
                    this.slidertarget = 0;
                } else {
                    this.slidertarget = no;
                }
            }
            this.slidercurrent = this.slidertarget;
            this.slidertarpos = this.slidertarget*this.slideritemw;
            this.slidertarpos = -this.slidertarpos;
            this.slideritems.removeClass('active').eq(this.slidertarget).addClass('active');
            this.slidernavs.removeClass('active').eq(this.slidertarget).addClass('active');
            this.slidercontainer.css('left',this.slidertarpos);
            switch (this.all) {
                case '#tables':
                    if(this.slidertarget == this.slidercount0) {
                        this.sliderdopnav.removeClass('active').eq(2).addClass('active');
                    } else {
                        if(this.slidertarget==this.slidercount0-1){
                            this.sliderdopnav.removeClass('active').eq(1).addClass('active');
                        } else {
                            this.sliderdopnav.removeClass('active').eq(0).addClass('active');
                        }
                    }
                    break;
                case '#disinfecting':
                    if(this.slidertarget == this.slidercount0) {
                        this.sliderdopnav.removeClass('active').eq(1).addClass('active');
                    } else {
                        this.sliderdopnav.removeClass('active').eq(0).addClass('active');
                    }
                    break;
            }

            this.sliderall.attr('data-select',this.slidertarget);
            this.formreinit();
        };


Тут в конце вызываем функцию перезагрузки формы (в зависимости от того какой слайд выбран - необходимо скрыть или показать определённые элементы формы)
  • Вопрос задан
  • 2591 просмотр
Пригласить эксперта
Ответы на вопрос 2
miraage
@miraage
Старый прогер
var self = this;
this.sliderall.find('a.next').click( function(event) {
    self.slidergoto(self.slidercurrent+1);
    return false;
});
Ответ написан
Комментировать
k12th
@k12th
console.log(`You're pulling my leg, right?`);
Formslider.prototype.setSlider = function () {
//...
    this.sliderall.find('a.next').click( function(event) {
        this.slidergoto(this.slidercurrent+1);
        return false;
    }.bind(this)); // не будет работать только в ие8-, но это поправимо
//....
};


Вообще посмотрите, как это решено в Backbone.View. Очень удобно работать, реализацию стыбрить -- дело пять минут.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы