我在Codrops form添加了一个后退按钮。
这是我网站上的webpage,其中包含已实施的表单。
问题在于,如果用户快速按下后退按钮(前一个问题),则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 :(得分:1)
修复:
a)更改第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 );
};
b)更改第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();
}
};
b)更改第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 :(得分:1)
你可以在控制台中看到你有一个"未捕获的DOMException:无法执行' removeChild' on'节点':要删除的节点不是此节点的子节点。在HTMLDivElement.onEndTransitionFn(http://dundaah.com/days/js/contactForm.js:255:26)"。
我怀疑当你快速按下按钮时,你几乎同时发送了两个事件,它们试图删除相同的节点(并可能在某处重新添加)。执行self.questionStatus.removeChild( self.nextQuestionNum );
答案 2 :(得分:1)
正在发生的是这个功能:
// 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 );
};
当按钮是上一个按钮或按下下一个按钮时,正在创建一个新的span元素。
之后调用函数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 );
};
答案 3 :(得分:1)
从每个人那里得到很好的澄清,当用户快速点击背面(或者下一个,脚本在下一次快速点击时断开)时,你会尝试删除那些不再存在的东西。快速修复可能是在onEndTransitionFn
函数中查询要选择的节点(第一个拾取的节点始终是您想要的节点)。
self
.nextQuestionNum
.parentNode
.removeChild(self.nextQuestionNum.parentNode.querySelector('.number-next'))