Я добавил кнопку «Назад» в форму Codrops.

Вот веб-страница с моего веб-сайта, на которой реализована форма.

Проблема заключается в том, что если пользователь быстро нажимает кнопку «назад» (для предыдущего вопроса), счетчик questionNumber перекрывается, и цифры в итоге выглядят смешанными.

Может ли кто-нибудь помочь?

Полный JavaScript и CSS Ниже приведены фрагменты кода.

.simform .number {
	position: absolute;
	right: 0;
	overflow: hidden;
	margin: 0.4em 0;
	width: 3em;
	font-weight: 700;
	font-size: 0.4em;
}

.simform .number:after {
	position: absolute;
	left: 50%;
	content: '/';
	opacity: 0.4;
	-webkit-transform: translateX(-50%);
	transform: translateX(-50%);
}

.simform .number span {
	float: right;
	width: 40%;
	text-align: center;
}

.simform .number .number-current {
	float: left;
}

.simform .number-next {
	position: absolute;
	left: 0;
}

.simform.show-next .number-current {
	-webkit-transition: -webkit-transform 0.4s;
	transition: transform 0.4s;
	-webkit-transform: translateY(-100%);
	transform: translateY(-100%);
}

.simform.show-next .number-next {
	-webkit-animation: moveUpFromDown 0.4s both;
	animation: moveUpFromDown 0.4s both;
}

.simform.show-previous .number-current {
	-webkit-transition: -webkit-transform 0.4s;
	transition: transform 0.4s;
	-webkit-transform: translateY(100%);
	transform: translateY(100%);
}

.simform.show-previous .number-next {
	-webkit-animation: moveDownFromUp 0.4s both;
	animation: moveDownFromUp 0.4s both;
}
0
Max Njoroge 8 Янв 2017 в 10:12

4 ответа

Лучший ответ

Исправление .

А) Изменить участок возле линии 275:

// changes the current question number
stepsForm.prototype._updateQuestionNumber = function() {

    if (this.nextQuestionNum) this.questionStatus.removeChild( this.nextQuestionNum ); // remove if it still exists (when user clicks forwards or back before animation ends)
    this.nextQuestionNum = document.createElement( 'span' );

    this.nextQuestionNum.className = 'number-next';
    this.nextQuestionNum.innerHTML = Number( this.current + 1 );
    // insert it in the DOM
    this.questionStatus.appendChild( this.nextQuestionNum );
};

Б) Изменить участок возле линии 195:

    // after animation ends, remove class "show-next" from form element and change current question placeholder
    var self = this,
        onEndTransitionFn = function( ev ) {
            if( support.transitions ) {
                this.removeEventListener( transEndEventName, onEndTransitionFn );
            }
            if( self.isFilled ) {
                self._submit();
            }
            else {
                classie.removeClass( self.el, 'show-next' );
                self.currentNum.innerHTML = self.nextQuestionNum.innerHTML;
                self.questionStatus.removeChild( self.nextQuestionNum );
                self.nextQuestionNum = null; // set to null to indicate that it has been removed

                // force the focus on the next input
                nextQuestion.querySelector( 'input' ).focus();
            }
        };

Б) Изменить участок возле линии 257:

    // after animation ends, remove class "show-previous" from form element and change current question placeholder
    var self = this,
        onEndTransitionFn = function( ev ) {
            if( support.transitions ) {
                this.removeEventListener( transEndEventName, onEndTransitionFn );
            }
            if( self.isFilled ) {
                self._submit();
            }
            else {
                classie.removeClass( self.el, 'show-previous' );
                self.currentNum.innerHTML = self.nextQuestionNum.innerHTML;
                self.questionStatus.removeChild( self.nextQuestionNum );
                self.nextQuestionNum = null; // set to null to indicate that it has been removed

                // force the focus on the next input
                previousQuestion.querySelector( 'input' ).focus();
            }
        };

Объяснение:

Проблема в этом разделе:

// changes the current question number
    stepsForm.prototype._updateQuestionNumber = function() {
        // first, create next question number placeholder
        this.nextQuestionNum = document.createElement( 'span' );
        this.nextQuestionNum.className = 'number-next';
        this.nextQuestionNum.innerHTML = Number( this.current + 1 );
        // insert it in the DOM
        this.questionStatus.appendChild( this.nextQuestionNum );
    };

В частности, строка this.nextQuestionNum = document.createElement( 'span' );.

Происходит то, что он создает span и содержит ссылку на него (this.nextQuestionNum). Как только анимация заканчивается, этот элемент уничтожается с использованием этой ссылки.

Когда пользователь щелкает слишком быстро (т. Е. Быстрее, чем запускается анимация), приведенный выше код выполняется во второй раз и создает новый span и содержит ссылку на него. В этот момент, если оригинал span не был удален, тогда код потерял свой указатель на него и зависает, как неприятный запах.

Таким образом, оператор if проверяет, не является ли он нулевым, и удаляет его.

1
K Scandrett 10 Янв 2017 в 09:04

Вы можете увидеть в консоли «Uncaught DOMException: не удалось выполнить« removeChild »на« узле »: удаляемый узел не является дочерним для этого узла. At HTMLDivElement.onEndTransitionFn (http://dundaah.com/days/js/contactForm.js:255:26)".

Я подозреваю, что когда вы быстро нажимаете на кнопку, вы почти отправляете два события одновременно, которые пытаются удалить один и тот же узел (и, возможно, повторно добавить его куда-нибудь). Вы должны убедиться, что узел Dom существует, когда вы делаете self.questionStatus.removeChild( self.nextQuestionNum );

1
ValLeNain 10 Янв 2017 в 09:06

Как всем очень хорошо известно, когда пользователь быстро нажимает на спину (или на следующий, сценарий разрывается с быстрыми нажатиями на следующую), вы пытаетесь удалить то, чего больше нет. Быстрое исправление может заключаться в том, чтобы сделать запрос на выбор узла, который вы хотите удалить (первым выбранным узлом всегда будет тот, который вы хотите) внутри вашей функции onEndTransitionFn.

self
    .nextQuestionNum
    .parentNode
    .removeChild(self.nextQuestionNum.parentNode.querySelector('.number-next'))
1
Daniele 10 Янв 2017 в 09:35

Что происходит, это функция:

// changes the current question number
stepsForm.prototype._updateQuestionNumber = function() {
    // first, create next question number placeholder
    this.nextQuestionNum = document.createElement( 'span' );
    this.nextQuestionNum.className = 'number-next';
    this.nextQuestionNum.innerHTML = Number( this.current + 1 );
    // insert it in the DOM
    this.questionStatus.appendChild( this.nextQuestionNum );
};

Создает новый элемент диапазона, когда кнопка является предыдущей кнопкой или нажата следующая кнопка. После чего вызывающая функция stepsForm.prototype._previousQuestion запускает этот блок кода:

// after animation ends, remove class "show-previous" from form element and change current question placeholder
        var self = this,
            onEndTransitionFn = function( ev ) {
                if( support.transitions ) {
                    this.removeEventListener( transEndEventName, onEndTransitionFn );
                }
                if( self.isFilled ) {
                    self._submit();
                }
                else {
                    classie.removeClass( self.el, 'show-previous' );
                    self.currentNum.innerHTML = self.nextQuestionNum.innerHTML;
                    self.questionStatus.removeChild( self.nextQuestionNum );
                    // force the focus on the next input
                    previousQuestion.querySelector( 'input' ).focus();
                }
            };

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

Вы можете попробовать переместить эту строку

self.questionStatus.removeChild( self.nextQuestionNum );

В функцию stepsForm.prototype._updateQuestionNumber с простой проверкой, чтобы избежать возможных ошибок, например:

// changes the current question number
stepsForm.prototype._updateQuestionNumber = function() {
    // if nextQuestionNum exists remove it
    if (this.nextQuestionNum.innerHTML){
        self.questionStatus.removeChild( self.nextQuestionNum );
    }
    // first, create next question number placeholder
    this.nextQuestionNum = document.createElement( 'span' );
    this.nextQuestionNum.className = 'number-next';
    this.nextQuestionNum.innerHTML = Number( this.current + 1 );
    // insert it in the DOM
    this.questionStatus.appendChild( this.nextQuestionNum );
};
1
Ben Davison 10 Янв 2017 в 09:17